📄 geometry.java
字号:
package org.sunflow.core;
import org.sunflow.SunflowAPI;
import org.sunflow.core.accel.NullAccelerator;
import org.sunflow.math.BoundingBox;
import org.sunflow.math.Matrix4;
import org.sunflow.system.UI;
import org.sunflow.system.UI.Module;
/**
* This class represent a geometric object in its native object space. These
* object are not rendered directly, they must be instanced via {@link Instance}.
* This class performs all the bookkeeping needed for on-demand tesselation and
* acceleration structure building.
*/
public class Geometry implements RenderObject {
private Tesselatable tesselatable;
private PrimitiveList primitives;
private AccelerationStructure accel;
private int builtAccel;
private int builtTess;
private String acceltype;
/**
* Create a geometry from the specified tesselatable object. The actual
* renderable primitives will be generated on demand.
*
* @param tesselatable tesselation object
*/
public Geometry(Tesselatable tesselatable) {
this.tesselatable = tesselatable;
primitives = null;
accel = null;
builtAccel = 0;
builtTess = 0;
acceltype = null;
}
/**
* Create a geometry from the specified primitive aggregate. The
* acceleration structure for this object will be built on demand.
*
* @param primitives primitive list object
*/
public Geometry(PrimitiveList primitives) {
tesselatable = null;
this.primitives = primitives;
accel = null;
builtAccel = 0;
builtTess = 1; // already tesselated
}
public boolean update(ParameterList pl, SunflowAPI api) {
acceltype = pl.getString("accel", acceltype);
// clear up old tesselation if it exists
if (tesselatable != null) {
primitives = null;
builtTess = 0;
}
// clear acceleration structure so it will be rebuilt
accel = null;
builtAccel = 0;
if (tesselatable != null)
return tesselatable.update(pl, api);
// update primitives
return primitives.update(pl, api);
}
int getNumPrimitives() {
return primitives == null ? 0 : primitives.getNumPrimitives();
}
BoundingBox getWorldBounds(Matrix4 o2w) {
if (primitives == null) {
BoundingBox b = tesselatable.getWorldBounds(o2w);
if (b != null)
return b;
if (builtTess == 0)
tesselate();
if (primitives == null)
return null; // failed tesselation, return infinite bounding
// box
}
return primitives.getWorldBounds(o2w);
}
void intersect(Ray r, IntersectionState state) {
if (builtTess == 0)
tesselate();
if (builtAccel == 0)
build();
accel.intersect(r, state);
}
private synchronized void tesselate() {
// double check flag
if (builtTess != 0)
return;
if (tesselatable != null && primitives == null) {
UI.printInfo(Module.GEOM, "Tesselating geometry ...");
primitives = tesselatable.tesselate();
if (primitives == null)
UI.printError(Module.GEOM, "Tesselation failed - geometry will be discarded");
else
UI.printDetailed(Module.GEOM, "Tesselation produced %d primitives", primitives.getNumPrimitives());
}
builtTess = 1;
}
private synchronized void build() {
// double check flag
if (builtAccel != 0)
return;
if (primitives != null) {
int n = primitives.getNumPrimitives();
if (n >= 1000)
UI.printInfo(Module.GEOM, "Building acceleration structure for %d primitives ...", n);
accel = AccelerationStructureFactory.create(acceltype, n, true);
accel.build(primitives);
} else {
// create an empty accelerator to avoid having to check for null
// pointers in the intersect method
accel = new NullAccelerator();
}
builtAccel = 1;
}
void prepareShadingState(ShadingState state) {
primitives.prepareShadingState(state);
}
PrimitiveList getBakingPrimitives() {
if (builtTess == 0)
tesselate();
if (primitives == null)
return null;
return primitives.getBakingPrimitives();
}
PrimitiveList getPrimitiveList() {
return primitives;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -