📄 beziermesh.java
字号:
public int getNumPrimitives() {
return patches.length;
}
public float getPrimitiveBound(int primID, int i) {
float[] patch = patches[primID];
int axis = i >>> 1;
if ((i & 1) == 0) {
float min = patch[axis];
for (int j = axis + 3; j < patch.length; j += 3)
if (min > patch[j])
min = patch[j];
return min;
} else {
float max = patch[axis];
for (int j = axis + 3; j < patch.length; j += 3)
if (max < patch[j])
max = patch[j];
return max;
}
}
public void intersectPrimitive(Ray r, int primID, IntersectionState state) {
// ray patch intersection
final float[] stack = state.getRobustStack();
final int STACKSIZE = 64;
{
// init patch
float[] patch = patches[primID];
for (int i = 0; i < 4 * 4 * 3; i++)
stack[i] = patch[i];
stack[48] = Float.POSITIVE_INFINITY; // bbox size
stack[49] = 0; // umin
stack[50] = 0; // vmin
stack[51] = 1; // umax
stack[52] = 1; // vmax
}
int stackpos = 0;
float orgX = r.ox, invDirX = 1 / r.dx;
float orgY = r.oy, invDirY = 1 / r.dy;
float orgZ = r.oz, invDirZ = 1 / r.dz;
float t1, t2;
while (stackpos >= 0) {
float intervalMin = r.getMin();
float intervalMax = r.getMax();
// x-axis bbox
float minx = stack[stackpos + 0];
float maxx = stack[stackpos + 0];
for (int j = 1, idx = stackpos + 3; j < 4 * 4; j++, idx += 3) {
if (minx > stack[idx])
minx = stack[idx];
if (maxx < stack[idx])
maxx = stack[idx];
}
t1 = (minx - orgX) * invDirX;
t2 = (maxx - orgX) * invDirX;
if (invDirX > 0) {
if (t1 > intervalMin)
intervalMin = t1;
if (t2 < intervalMax)
intervalMax = t2;
} else {
if (t2 > intervalMin)
intervalMin = t2;
if (t1 < intervalMax)
intervalMax = t1;
}
if (intervalMin > intervalMax) {
stackpos -= STACKSIZE;
continue;
}
// y-axis bbox
float miny = stack[stackpos + 1];
float maxy = stack[stackpos + 1];
for (int j = 1, idx = stackpos + 4; j < 4 * 4; j++, idx += 3) {
if (miny > stack[idx])
miny = stack[idx];
if (maxy < stack[idx])
maxy = stack[idx];
}
t1 = (miny - orgY) * invDirY;
t2 = (maxy - orgY) * invDirY;
if (invDirY > 0) {
if (t1 > intervalMin)
intervalMin = t1;
if (t2 < intervalMax)
intervalMax = t2;
} else {
if (t2 > intervalMin)
intervalMin = t2;
if (t1 < intervalMax)
intervalMax = t1;
}
if (intervalMin > intervalMax) {
stackpos -= STACKSIZE;
continue;
}
// z-axis bbox
float minz = stack[stackpos + 2];
float maxz = stack[stackpos + 2];
for (int j = 1, idx = stackpos + 5; j < 4 * 4; j++, idx += 3) {
if (minz > stack[idx])
minz = stack[idx];
if (maxz < stack[idx])
maxz = stack[idx];
}
t1 = (minz - orgZ) * invDirZ;
t2 = (maxz - orgZ) * invDirZ;
if (invDirZ > 0) {
if (t1 > intervalMin)
intervalMin = t1;
if (t2 < intervalMax)
intervalMax = t2;
} else {
if (t2 > intervalMin)
intervalMin = t2;
if (t1 < intervalMax)
intervalMax = t1;
}
if (intervalMin > intervalMax) {
stackpos -= STACKSIZE;
continue;
}
// intersection was found - keep going
float size = (maxx - minx) + (maxy - miny) + (maxz - minz);
if (Float.floatToRawIntBits(stack[stackpos + 48]) == Float.floatToRawIntBits(size)) {
// L1 norm is 0, we are done
r.setMax(intervalMin);
state.setIntersection(primID, stack[stackpos + 49], stack[stackpos + 50]);
stackpos -= STACKSIZE;
continue;
}
// not small enough yet - subdivide
// lets pick a subdivision axis first:
float sizeu = 0;
float sizev = 0;
for (int i = 0; i < 3; i++) {
sizeu += Math.abs(stack[stackpos + (0 * 4 + 3) * 3 + i] - stack[stackpos + i]);
sizev += Math.abs(stack[stackpos + (3 * 4 + 0) * 3 + i] - stack[stackpos + i]);
}
if (sizeu > sizev) {
// split in U direction
for (int i = 0; i < 4; i++) {
for (int axis = 0; axis < 3; axis++) {
// load data
float p0 = stack[stackpos + (i * 4 + 0) * 3 + axis];
float p1 = stack[stackpos + (i * 4 + 1) * 3 + axis];
float p2 = stack[stackpos + (i * 4 + 2) * 3 + axis];
float p3 = stack[stackpos + (i * 4 + 3) * 3 + axis];
// Split curve in the middle
float q0 = p0;
float q1 = (p0 + p1) * 0.5f;
float q2 = q1 * 0.5f + (p1 + p2) * 0.25f;
float r3 = p3;
float r2 = (p2 + p3) * 0.5f;
float r1 = r2 * 0.5f + (p1 + p2) * 0.25f;
float q3 = (q2 + r1) * 0.5f;
float r0 = q3;
// load new curve data into the stack
stack[stackpos + (i * 4 + 0) * 3 + axis] = q0;
stack[stackpos + (i * 4 + 1) * 3 + axis] = q1;
stack[stackpos + (i * 4 + 2) * 3 + axis] = q2;
stack[stackpos + (i * 4 + 3) * 3 + axis] = q3;
stack[stackpos + STACKSIZE + (i * 4 + 0) * 3 + axis] = r0;
stack[stackpos + STACKSIZE + (i * 4 + 1) * 3 + axis] = r1;
stack[stackpos + STACKSIZE + (i * 4 + 2) * 3 + axis] = r2;
stack[stackpos + STACKSIZE + (i * 4 + 3) * 3 + axis] = r3;
}
}
// copy current bbox size
stack[stackpos + 48] = stack[stackpos + STACKSIZE + 48] = size;
// finally - split uv ranges
float umin = stack[stackpos + 49];
float umax = stack[stackpos + 51];
stack[stackpos + 49] = umin;
stack[stackpos + STACKSIZE + 50] = stack[stackpos + 50];
stack[stackpos + 51] = stack[stackpos + STACKSIZE + 49] = (umin + umax) * 0.5f;
stack[stackpos + STACKSIZE + 51] = umax;
stack[stackpos + STACKSIZE + 52] = stack[stackpos + 52];
} else {
// split in V direction
for (int i = 0; i < 4; i++) {
for (int axis = 0; axis < 3; axis++) {
// load data
float p0 = stack[stackpos + (0 * 4 + i) * 3 + axis];
float p1 = stack[stackpos + (1 * 4 + i) * 3 + axis];
float p2 = stack[stackpos + (2 * 4 + i) * 3 + axis];
float p3 = stack[stackpos + (3 * 4 + i) * 3 + axis];
// Split curve in the middle
float q0 = p0;
float q1 = (p0 + p1) * 0.5f;
float q2 = q1 * 0.5f + (p1 + p2) * 0.25f;
float r3 = p3;
float r2 = (p2 + p3) * 0.5f;
float r1 = r2 * 0.5f + (p1 + p2) * 0.25f;
float q3 = (q2 + r1) * 0.5f;
float r0 = q3;
// load new curve data into the stack
stack[stackpos + (0 * 4 + i) * 3 + axis] = q0;
stack[stackpos + (1 * 4 + i) * 3 + axis] = q1;
stack[stackpos + (2 * 4 + i) * 3 + axis] = q2;
stack[stackpos + (3 * 4 + i) * 3 + axis] = q3;
stack[stackpos + STACKSIZE + (0 * 4 + i) * 3 + axis] = r0;
stack[stackpos + STACKSIZE + (1 * 4 + i) * 3 + axis] = r1;
stack[stackpos + STACKSIZE + (2 * 4 + i) * 3 + axis] = r2;
stack[stackpos + STACKSIZE + (3 * 4 + i) * 3 + axis] = r3;
}
}
// copy current bbox size
stack[stackpos + 48] = stack[stackpos + STACKSIZE + 48] = size;
// finally - split uv ranges
float vmin = stack[stackpos + 50];
float vmax = stack[stackpos + 52];
stack[stackpos + STACKSIZE + 49] = stack[stackpos + 49];
stack[stackpos + 50] = vmin;
stack[stackpos + 52] = stack[stackpos + STACKSIZE + 50] = (vmin + vmax) * 0.5f;
stack[stackpos + STACKSIZE + 51] = stack[stackpos + 51];
stack[stackpos + STACKSIZE + 52] = vmax;
}
stackpos += STACKSIZE;
}
}
public void prepareShadingState(ShadingState state) {
state.init();
state.getRay().getPoint(state.getPoint());
Instance parent = state.getInstance();
float u = state.getU();
float v = state.getV();
float[] bu = bernstein(u);
float[] bdu = bernsteinDeriv(u);
float[] bv = bernstein(v);
float[] bdv = bernsteinDeriv(v);
getPatchPoint(u, v, patches[state.getPrimitiveID()], bu, bv, bdu, bdv, new Point3(), state.getNormal());
state.getNormal().set(parent.transformNormalObjectToWorld(state.getNormal()));
state.getNormal().normalize();
state.getGeoNormal().set(state.getNormal());
state.getUV().set(u, v);
state.setShader(parent.getShader(0));
state.setModifier(parent.getModifier(0));
// FIXME: use actual derivatives to create basis
state.setBasis(OrthoNormalBasis.makeFromW(state.getNormal()));
}
public PrimitiveList getBakingPrimitives() {
return null;
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -