📄 scparser.java
字号:
package org.sunflow.core.parser;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.StringReader;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import org.codehaus.janino.ClassBodyEvaluator;
import org.codehaus.janino.CompileException;
import org.codehaus.janino.Scanner;
import org.codehaus.janino.Parser.ParseException;
import org.codehaus.janino.Scanner.ScanException;
import org.sunflow.SunflowAPI;
import org.sunflow.core.PrimitiveList;
import org.sunflow.core.SceneParser;
import org.sunflow.core.Shader;
import org.sunflow.core.Tesselatable;
import org.sunflow.core.camera.FisheyeLens;
import org.sunflow.core.camera.PinholeLens;
import org.sunflow.core.camera.SphericalLens;
import org.sunflow.core.camera.ThinLens;
import org.sunflow.core.light.DirectionalSpotlight;
import org.sunflow.core.light.ImageBasedLight;
import org.sunflow.core.light.PointLight;
import org.sunflow.core.light.SphereLight;
import org.sunflow.core.light.SunSkyLight;
import org.sunflow.core.light.TriangleMeshLight;
import org.sunflow.core.modifiers.BumpMappingModifier;
import org.sunflow.core.modifiers.NormalMapModifier;
import org.sunflow.core.primitive.Background;
import org.sunflow.core.primitive.BanchoffSurface;
import org.sunflow.core.primitive.CornellBox;
import org.sunflow.core.primitive.Hair;
import org.sunflow.core.primitive.JuliaFractal;
import org.sunflow.core.primitive.ParticleSurface;
import org.sunflow.core.primitive.Plane;
import org.sunflow.core.primitive.Sphere;
import org.sunflow.core.primitive.Torus;
import org.sunflow.core.primitive.TriangleMesh;
import org.sunflow.core.shader.AmbientOcclusionShader;
import org.sunflow.core.shader.AnisotropicWardShader;
import org.sunflow.core.shader.ConstantShader;
import org.sunflow.core.shader.DiffuseShader;
import org.sunflow.core.shader.GlassShader;
import org.sunflow.core.shader.IDShader;
import org.sunflow.core.shader.MirrorShader;
import org.sunflow.core.shader.PhongShader;
import org.sunflow.core.shader.ShinyDiffuseShader;
import org.sunflow.core.shader.TexturedAmbientOcclusionShader;
import org.sunflow.core.shader.TexturedDiffuseShader;
import org.sunflow.core.shader.TexturedPhongShader;
import org.sunflow.core.shader.TexturedShinyDiffuseShader;
import org.sunflow.core.shader.TexturedWardShader;
import org.sunflow.core.shader.UberShader;
import org.sunflow.core.shader.ViewCausticsShader;
import org.sunflow.core.shader.ViewGlobalPhotonsShader;
import org.sunflow.core.shader.ViewIrradianceShader;
import org.sunflow.core.tesselatable.BezierMesh;
import org.sunflow.core.tesselatable.FileMesh;
import org.sunflow.core.tesselatable.Gumbo;
import org.sunflow.core.tesselatable.Teapot;
import org.sunflow.image.Color;
import org.sunflow.math.Matrix4;
import org.sunflow.math.Point3;
import org.sunflow.math.Vector3;
import org.sunflow.system.Parser;
import org.sunflow.system.Timer;
import org.sunflow.system.UI;
import org.sunflow.system.Parser.ParserException;
import org.sunflow.system.UI.Module;
/**
* This class provides a static method for loading files in the Sunflow scene
* file format.
*/
public class SCParser implements SceneParser {
private Parser p;
private int numLightSamples;
public SCParser() {
}
public boolean parse(String filename, SunflowAPI api) {
String localDir = new File(filename).getAbsoluteFile().getParentFile().getAbsolutePath();
numLightSamples = 1;
Timer timer = new Timer();
timer.start();
UI.printInfo(Module.API, "Parsing \"%s\" ...", filename);
try {
p = new Parser(filename);
while (true) {
String token = p.getNextToken();
if (token == null)
break;
if (token.equals("image")) {
UI.printInfo(Module.API, "Reading image settings ...");
parseImageBlock(api);
} else if (token.equals("background")) {
UI.printInfo(Module.API, "Reading background ...");
parseBackgroundBlock(api);
} else if (token.equals("accel")) {
UI.printInfo(Module.API, "Reading accelerator type ...");
p.getNextToken();
UI.printWarning(Module.API, "Setting accelerator type is not recommended - ignoring");
} else if (token.equals("filter")) {
UI.printInfo(Module.API, "Reading image filter type ...");
parseFilter(api);
} else if (token.equals("bucket")) {
UI.printInfo(Module.API, "Reading bucket settings ...");
api.parameter("bucket.size", p.getNextInt());
api.parameter("bucket.order", p.getNextToken());
api.options(SunflowAPI.DEFAULT_OPTIONS);
} else if (token.equals("photons")) {
UI.printInfo(Module.API, "Reading photon settings ...");
parsePhotonBlock(api);
} else if (token.equals("gi")) {
UI.printInfo(Module.API, "Reading global illumination settings ...");
parseGIBlock(api);
} else if (token.equals("lightserver")) {
UI.printInfo(Module.API, "Reading light server settings ...");
parseLightserverBlock(api);
} else if (token.equals("trace-depths")) {
UI.printInfo(Module.API, "Reading trace depths ...");
parseTraceBlock(api);
} else if (token.equals("camera")) {
parseCamera(api);
} else if (token.equals("shader")) {
if (!parseShader(api))
return false;
} else if (token.equals("modifier")) {
if (!parseModifier(api))
return false;
} else if (token.equals("override")) {
api.shaderOverride(p.getNextToken(), p.getNextBoolean());
} else if (token.equals("object")) {
parseObjectBlock(api);
} else if (token.equals("instance")) {
parseInstanceBlock(api);
} else if (token.equals("light")) {
parseLightBlock(api);
} else if (token.equals("texturepath")) {
String path = p.getNextToken();
if (!new File(path).isAbsolute())
path = localDir + File.separator + path;
api.addTextureSearchPath(path);
} else if (token.equals("includepath")) {
String path = p.getNextToken();
if (!new File(path).isAbsolute())
path = localDir + File.separator + path;
api.addIncludeSearchPath(path);
} else if (token.equals("include")) {
String file = p.getNextToken();
UI.printInfo(Module.API, "Including: \"%s\" ...", file);
api.parse(file);
} else
UI.printWarning(Module.API, "Unrecognized token %s", token);
}
p.close();
} catch (ParserException e) {
UI.printError(Module.API, "%s", e.getMessage());
e.printStackTrace();
return false;
} catch (FileNotFoundException e) {
UI.printError(Module.API, "%s", e.getMessage());
return false;
} catch (IOException e) {
UI.printError(Module.API, "%s", e.getMessage());
return false;
}
timer.end();
UI.printInfo(Module.API, "Done parsing.");
UI.printInfo(Module.API, "Parsing time: %s", timer.toString());
return true;
}
private void parseImageBlock(SunflowAPI api) throws IOException, ParserException {
p.checkNextToken("{");
if (p.peekNextToken("resolution")) {
api.parameter("resolutionX", p.getNextInt());
api.parameter("resolutionY", p.getNextInt());
}
if (p.peekNextToken("aa")) {
api.parameter("aa.min", p.getNextInt());
api.parameter("aa.max", p.getNextInt());
}
if (p.peekNextToken("samples"))
api.parameter("aa.samples", p.getNextInt());
if (p.peekNextToken("contrast"))
api.parameter("aa.contrast", p.getNextFloat());
if (p.peekNextToken("filter"))
api.parameter("filter", p.getNextToken());
if (p.peekNextToken("jitter"))
api.parameter("aa.jitter", p.getNextBoolean());
if (p.peekNextToken("show-aa")) {
UI.printWarning(Module.API, "Deprecated: show-aa ignored");
p.getNextBoolean();
}
if (p.peekNextToken("output")) {
UI.printWarning(Module.API, "Deprecated: output statement ignored");
p.getNextToken();
}
api.options(SunflowAPI.DEFAULT_OPTIONS);
p.checkNextToken("}");
}
private void parseBackgroundBlock(SunflowAPI api) throws IOException, ParserException {
p.checkNextToken("{");
p.checkNextToken("color");
api.parameter("color", parseColor());
api.shader("background.shader", new ConstantShader());
api.geometry("background", new Background());
api.parameter("shaders", "background.shader");
api.instance("background.instance", "background");
p.checkNextToken("}");
}
private void parseFilter(SunflowAPI api) throws IOException, ParserException {
UI.printWarning(Module.API, "Deprecated keyword \"filter\" - set this option in the image block");
String name = p.getNextToken();
api.parameter("filter", name);
api.options(SunflowAPI.DEFAULT_OPTIONS);
boolean hasSizeParams = name.equals("box") || name.equals("gaussian") || name.equals("blackman-harris") || name.equals("sinc") || name.equals("triangle");
if (hasSizeParams) {
p.getNextFloat();
p.getNextFloat();
}
}
private void parsePhotonBlock(SunflowAPI api) throws ParserException, IOException {
int numEmit = 0;
boolean globalEmit = false;
p.checkNextToken("{");
if (p.peekNextToken("emit")) {
UI.printWarning(Module.API, "Shared photon emit values are deprectated - specify number of photons to emit per map");
numEmit = p.getNextInt();
globalEmit = true;
}
if (p.peekNextToken("global")) {
UI.printWarning(Module.API, "Global photon map setting belonds inside the gi block - ignoring");
if (!globalEmit)
p.getNextInt();
p.getNextToken();
p.getNextInt();
p.getNextFloat();
}
p.checkNextToken("caustics");
if (!globalEmit)
numEmit = p.getNextInt();
api.parameter("caustics.emit", numEmit);
api.parameter("caustics", p.getNextToken());
api.parameter("caustics.gather", p.getNextInt());
api.parameter("caustics.radius", p.getNextFloat());
api.options(SunflowAPI.DEFAULT_OPTIONS);
p.checkNextToken("}");
}
private void parseGIBlock(SunflowAPI api) throws ParserException, IOException {
p.checkNextToken("{");
p.checkNextToken("type");
if (p.peekNextToken("irr-cache")) {
api.parameter("gi.engine", "irr-cache");
p.checkNextToken("samples");
api.parameter("gi.irr-cache.samples", p.getNextInt());
p.checkNextToken("tolerance");
api.parameter("gi.irr-cache.tolerance", p.getNextFloat());
p.checkNextToken("spacing");
api.parameter("gi.irr-cache.min_spacing", p.getNextFloat());
api.parameter("gi.irr-cache.max_spacing", p.getNextFloat());
// parse global photon map info
if (p.peekNextToken("global")) {
api.parameter("gi.irr-cache.gmap.emit", p.getNextInt());
api.parameter("gi.irr-cache.gmap", p.getNextToken());
api.parameter("gi.irr-cache.gmap.gather", p.getNextInt());
api.parameter("gi.irr-cache.gmap.radius", p.getNextFloat());
}
} else if (p.peekNextToken("path")) {
api.parameter("gi.engine", "path");
p.checkNextToken("samples");
api.parameter("gi.path.samples", p.getNextInt());
if (p.peekNextToken("bounces")) {
UI.printWarning(Module.API, "Deprecated setting: bounces - use diffuse trace depth instead");
p.getNextInt();
}
} else if (p.peekNextToken("fake")) {
api.parameter("gi.engine", "fake");
p.checkNextToken("up");
api.parameter("gi.fake.up", parseVector());
p.checkNextToken("sky");
api.parameter("gi.fake.sky", parseColor());
p.checkNextToken("ground");
api.parameter("gi.fake.ground", parseColor());
} else if (p.peekNextToken("igi")) {
api.parameter("gi.engine", "igi");
p.checkNextToken("samples");
api.parameter("gi.igi.samples", p.getNextInt());
p.checkNextToken("sets");
api.parameter("gi.igi.sets", p.getNextInt());
if (!p.peekNextToken("b"))
p.checkNextToken("c");
api.parameter("gi.igi.c", p.getNextFloat());
p.checkNextToken("bias-samples");
api.parameter("gi.igi.bias_samples", p.getNextInt());
} else if (p.peekNextToken("ambocc")) {
api.parameter("gi.engine", "ambocc");
p.checkNextToken("bright");
api.parameter("gi.ambocc.bright", parseColor());
p.checkNextToken("dark");
api.parameter("gi.ambocc.dark", parseColor());
p.checkNextToken("samples");
api.parameter("gi.ambocc.samples", p.getNextInt());
if (p.peekNextToken("maxdist"))
api.parameter("gi.ambocc.maxdist", p.getNextFloat());
} else if (p.peekNextToken("none") || p.peekNextToken("null")) {
// disable GI
api.parameter("gi.engine", "none");
} else
UI.printWarning(Module.API, "Unrecognized gi engine type \"%s\" - ignoring", p.getNextToken());
api.options(SunflowAPI.DEFAULT_OPTIONS);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -