code: package org.sunflow.core.parser;
  
  import java.io.File;
  import java.io.FileInputStream;
  import java.io.FileNotFoundException;
  import java.io.IOException;
  import java.nio.ByteOrder;
  import java.nio.FloatBuffer;
  import java.nio.MappedByteBuffer;
  import java.nio.channels.FileChannel;
  
  import org.sunflow.SunflowAPI;
  import org.sunflow.SunflowAPIInterface;
  import org.sunflow.core.SceneParser;
  import org.sunflow.math.Point3;
  import org.sunflow.math.Vector3;
  import org.sunflow.system.Parser;
  import org.sunflow.system.UI;
  import org.sunflow.system.UI.Module;
  
  public class RA2Parser implements SceneParser {
      public boolean parse(String filename, SunflowAPIInterface api) {
          try {
              UI.printInfo(Module.USER, "RA2 - Reading geometry: \"%s\" ...", filename);
              File file = new File(filename);
              FileInputStream stream = new FileInputStream(filename);
              MappedByteBuffer map = stream.getChannel().map(FileChannel.MapMode.READ_ONLY, 0, file.length());
              map.order(ByteOrder.LITTLE_ENDIAN);
              FloatBuffer buffer = map.asFloatBuffer();
              float[] data = new float[buffer.capacity()];
              for (int i = 0; i < data.length; i++)
                  data[i] = buffer.get(i);
              stream.close();
              api.parameter("points", "point", "vertex", data);
              int[] triangles = new int[3 * (data.length / 9)];
              for (int i = 0; i < triangles.length; i++)
                  triangles[i] = i;
              // create geo
              api.parameter("triangles", triangles);
              api.geometry(filename, "triangle_mesh");
              // create shader
              api.shader(filename + ".shader", "simple");
              // create instance
              api.parameter("shaders", filename + ".shader");
              api.instance(filename + ".instance", filename);
          } catch (FileNotFoundException e) {
              e.printStackTrace();
              return false;
          } catch (IOException e) {
              e.printStackTrace();
              return false;
          }
          try {
              filename = filename.replace(".ra2", ".txt");
              UI.printInfo(Module.USER, "RA2 - Reading camera  : \"%s\" ...", filename);
              Parser p = new Parser(filename);
              Point3 eye = new Point3();
              eye.x = p.getNextFloat();
              eye.y = p.getNextFloat();
              eye.z = p.getNextFloat();
              Point3 to = new Point3();
              to.x = p.getNextFloat();
              to.y = p.getNextFloat();
              to.z = p.getNextFloat();
              Vector3 up = new Vector3();
              switch (p.getNextInt()) {
                  case 0:
                      up.set(1, 0, 0);
                      break;
                  case 1:
                      up.set(0, 1, 0);
                      break;
                  case 2:
                      up.set(0, 0, 1);
                      break;
                  default:
                      UI.printWarning(Module.USER, "RA2 - Invalid up vector specification - using Z axis");
                      up.set(0, 0, 1);
                      break;
              }
              api.parameter("eye", eye);
              api.parameter("target", to);
              api.parameter("up", up);
              String cameraName = filename + ".camera";
              api.parameter("fov", 80f);
              api.camera(cameraName, "pinhole");
              api.parameter("camera", cameraName);
              api.parameter("resolutionX", 1024);
              api.parameter("resolutionY", 1024);
              api.options(SunflowAPI.DEFAULT_OPTIONS);
              p.close();
          } catch (FileNotFoundException e) {
              UI.printWarning(Module.USER, "RA2 - Camera file not found");
          } catch (IOException e) {
              e.printStackTrace();
              return false;
          }
          return true;
      }
  }