package com.exh.bevel; import com.exh.math.primitive.Geo; import com.exh.math.primitive.Point3; import com.exh.math.primitive.Quad; public class SurfaceShader { public final static class Params { public double mZ = 0; public final Point3 mN = new Point3(); } private final double[] mX = new double[2]; // 0 = left, 1 = right private final double[] mZ = new double[2]; private final Point3[] mN = Point3.newArray(2); private final Point3 mA = new Point3(), mB = new Point3(), mOut = new Point3(); // Call setTo() with a Y value first. void getAt(final double x, final Params p) { final double pos = (x-mX[0]) / (mX[1]-mX[0]); p.mZ = (mZ[0] * (1-pos)) + (mZ[1] * pos); p.mN.x = (mN[0].x * (1-pos)) + (mN[1].x * pos); p.mN.y = (mN[0].y * (1-pos)) + (mN[1].y * pos); p.mN.z = (mN[0].z * (1-pos)) + (mN[1].z * pos); } void setTo(final Surface s, final double y) { mA.y = mB.y = y; mA.x = s.mL-1; mB.x = s.mR+1; mZ[0] = 0; mZ[1] = 0; mX[0] = 1000000; mX[1] = -1000000; double minY = 0, maxY = 0; int minK = -1, maxK = -1; Point3 prev = s.mQ.mPt[Quad.SIZE-1]; final boolean isTri = s.mQ.mPt[1].sameAs(s.mQ.mPt[2]); for (int k=0; k mX[1]) { mX[1] = mOut.x; maxY = mOut.y; maxK = k; } } } prev = next; } if (minK < 0) { System.out.println("Error in shader y=" + y + " q=" + s.mQ); return; } // Interpolate the left and right sides fill(s, minK, minY, 0); fill(s, maxK, maxY, 1); } private final void fill(final Surface s, final int idx, final double y, final int dst) { final int pidx = (idx <= 0 ? Quad.SIZE-1 : idx-1); Point3 prev = s.mQ.mPt[pidx]; Point3 next = s.mQ.mPt[idx]; final double segD = Geo.dist(prev.x, prev.y, next.x, next.y), ptD = Geo.dist(prev.x, prev.y, mX[dst], y); final double pos = ptD / segD; // Depth mZ[dst] = ((prev.z * (1-pos)) + (next.z * pos)); // Normal prev = s.mPtNormal[pidx]; next = s.mPtNormal[idx]; mN[dst].x = ((prev.x * (1-pos)) + (next.x * pos)); mN[dst].y = ((prev.y * (1-pos)) + (next.y * pos)); mN[dst].z = ((prev.z * (1-pos)) + (next.z * pos)); } }