public Color GetRadiance(ShadingState state) { Point3[] p = new Point3[3]; if (!state.getTrianglePoints(p)) return getFillColor(state); // transform points into camera space Point3 center = state.getPoint(); Matrix4 w2c = state.getWorldToCamera(); center = w2c.transformP(center); for (int i = 0; i < 3; i++) p[i] = w2c.transformP(state.transformObjectToWorld(p[i])); float cn = 1.0f / (float)Math.Sqrt(center.x * center.x + center.y * center.y + center.z * center.z); for (int i = 0, i2 = 2; i < 3; i2 = i, i++) { // compute orthogonal projection of the shading point onto each // triangle edge as in: // http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html float t = (center.x - p[i].x) * (p[i2].x - p[i].x); t += (center.y - p[i].y) * (p[i2].y - p[i].y); t += (center.z - p[i].z) * (p[i2].z - p[i].z); t /= p[i].distanceToSquared(p[i2]); float projx = (1 - t) * p[i].x + t * p[i2].x; float projy = (1 - t) * p[i].y + t * p[i2].y; float projz = (1 - t) * p[i].z + t * p[i2].z; float n = 1.0f / (float)Math.Sqrt(projx * projx + projy * projy + projz * projz); // check angular width float dot = projx * center.x + projy * center.y + projz * center.z; if (dot * n * cn >= cosWidth) return getLineColor(state); } return getFillColor(state); }
public Color GetRadiance(ShadingState state) { Point3[] p = new Point3[3]; if (!state.getTrianglePoints(p)) { return(getFillColor(state)); } // transform points into camera space Point3 center = state.getPoint(); Matrix4 w2c = state.getWorldToCamera(); center = w2c.transformP(center); for (int i = 0; i < 3; i++) { p[i] = w2c.transformP(state.transformObjectToWorld(p[i])); } float cn = 1.0f / (float)Math.Sqrt(center.x * center.x + center.y * center.y + center.z * center.z); for (int i = 0, i2 = 2; i < 3; i2 = i, i++) { // compute orthogonal projection of the shading point onto each // triangle edge as in: // http://mathworld.wolfram.com/Point-LineDistance3-Dimensional.html float t = (center.x - p[i].x) * (p[i2].x - p[i].x); t += (center.y - p[i].y) * (p[i2].y - p[i].y); t += (center.z - p[i].z) * (p[i2].z - p[i].z); t /= p[i].distanceToSquared(p[i2]); float projx = (1 - t) * p[i].x + t * p[i2].x; float projy = (1 - t) * p[i].y + t * p[i2].y; float projz = (1 - t) * p[i].z + t * p[i2].z; float n = 1.0f / (float)Math.Sqrt(projx * projx + projy * projy + projz * projz); // check angular width float dot = projx * center.x + projy * center.y + projz * center.z; if (dot * n * cn >= cosWidth) { return(getLineColor(state)); } } return(getFillColor(state)); }
public void prepareShadingState(ShadingState state) { state.init(); Instance parent = state.getInstance(); int primID = state.getPrimitiveID(); float u = state.getU(); float v = state.getV(); float w = 1 - u - v; // state.getRay().getPoint(state.getPoint()); int tri = 3 * primID; int index0 = triangleMesh.triangles[tri + 0]; int index1 = triangleMesh.triangles[tri + 1]; int index2 = triangleMesh.triangles[tri + 2]; Point3 v0p = triangleMesh.getPoint(index0); Point3 v1p = triangleMesh.getPoint(index1); Point3 v2p = triangleMesh.getPoint(index2); // get object space point from barycentric coordinates state.getPoint().x = w * v0p.x + u * v1p.x + v * v2p.x; state.getPoint().y = w * v0p.y + u * v1p.y + v * v2p.y; state.getPoint().z = w * v0p.z + u * v1p.z + v * v2p.z; // move into world space state.getPoint().set(state.transformObjectToWorld(state.getPoint())); Vector3 ng = Point3.normal(v0p, v1p, v2p); if (parent != null) { ng = state.transformNormalObjectToWorld(ng); } ng.normalize(); state.getGeoNormal().set(ng); switch (triangleMesh.normals.interp) { case ParameterList.InterpolationType.NONE: case ParameterList.InterpolationType.FACE: { state.getNormal().set(ng); break; } case ParameterList.InterpolationType.VERTEX: { int i30 = 3 * index0; int i31 = 3 * index1; int i32 = 3 * index2; float[] normals = triangleMesh.normals.data; state.getNormal().x = w * normals[i30 + 0] + u * normals[i31 + 0] + v * normals[i32 + 0]; state.getNormal().y = w * normals[i30 + 1] + u * normals[i31 + 1] + v * normals[i32 + 1]; state.getNormal().z = w * normals[i30 + 2] + u * normals[i31 + 2] + v * normals[i32 + 2]; if (parent != null) { state.getNormal().set(state.transformNormalObjectToWorld(state.getNormal())); } state.getNormal().normalize(); break; } case ParameterList.InterpolationType.FACEVARYING: { int idx = 3 * tri; float[] normals = triangleMesh.normals.data; state.getNormal().x = w * normals[idx + 0] + u * normals[idx + 3] + v * normals[idx + 6]; state.getNormal().y = w * normals[idx + 1] + u * normals[idx + 4] + v * normals[idx + 7]; state.getNormal().z = w * normals[idx + 2] + u * normals[idx + 5] + v * normals[idx + 8]; if (parent != null) { state.getNormal().set(state.transformNormalObjectToWorld(state.getNormal())); } state.getNormal().normalize(); break; } } float uv00 = 0, uv01 = 0, uv10 = 0, uv11 = 0, uv20 = 0, uv21 = 0; switch (triangleMesh.uvs.interp) { case ParameterList.InterpolationType.NONE: case ParameterList.InterpolationType.FACE: { state.getUV().x = 0; state.getUV().y = 0; break; } case ParameterList.InterpolationType.VERTEX: { int i20 = 2 * index0; int i21 = 2 * index1; int i22 = 2 * index2; float[] uvs = triangleMesh.uvs.data; uv00 = uvs[i20 + 0]; uv01 = uvs[i20 + 1]; uv10 = uvs[i21 + 0]; uv11 = uvs[i21 + 1]; uv20 = uvs[i22 + 0]; uv21 = uvs[i22 + 1]; break; } case ParameterList.InterpolationType.FACEVARYING: { int idx = tri << 1; float[] uvs = triangleMesh.uvs.data; uv00 = uvs[idx + 0]; uv01 = uvs[idx + 1]; uv10 = uvs[idx + 2]; uv11 = uvs[idx + 3]; uv20 = uvs[idx + 4]; uv21 = uvs[idx + 5]; break; } } if (triangleMesh.uvs.interp != ParameterList.InterpolationType.NONE) { // get exact uv coords and compute tangent vectors state.getUV().x = w * uv00 + u * uv10 + v * uv20; state.getUV().y = w * uv01 + u * uv11 + v * uv21; float du1 = uv00 - uv20; float du2 = uv10 - uv20; float dv1 = uv01 - uv21; float dv2 = uv11 - uv21; Vector3 dp1 = Point3.sub(v0p, v2p, new Vector3()), dp2 = Point3.sub(v1p, v2p, new Vector3()); float determinant = du1 * dv2 - dv1 * du2; if (determinant == 0.0f) { // create basis in world space state.setBasis(OrthoNormalBasis.makeFromW(state.getNormal())); } else { float invdet = 1 / determinant; // Vector3 dpdu = new Vector3(); // dpdu.x = (dv2 * dp1.x - dv1 * dp2.x) * invdet; // dpdu.y = (dv2 * dp1.y - dv1 * dp2.y) * invdet; // dpdu.z = (dv2 * dp1.z - dv1 * dp2.z) * invdet; Vector3 dpdv = new Vector3(); dpdv.x = (-du2 * dp1.x + du1 * dp2.x) * invdet; dpdv.y = (-du2 * dp1.y + du1 * dp2.y) * invdet; dpdv.z = (-du2 * dp1.z + du1 * dp2.z) * invdet; if (parent != null) { dpdv = state.transformVectorObjectToWorld(dpdv); } // create basis in world space state.setBasis(OrthoNormalBasis.makeFromWV(state.getNormal(), dpdv)); } } else { state.setBasis(OrthoNormalBasis.makeFromW(state.getNormal())); } int shaderIndex = triangleMesh.faceShaders == null ? 0 : (triangleMesh.faceShaders[primID] & 0xFF); state.setShader(parent.getShader(shaderIndex)); }