📄 trianglemesh.java
字号:
if ( x > maxX ) maxX = x; if ( y > maxY ) maxY = y; if ( z > maxZ ) maxZ = z; } minMax[0] = minX; minMax[1] = minY; minMax[2] = minZ; minMax[3] = maxX; minMax[4] = maxY; minMax[5] = maxZ; } } /** This method is supposed to be a friend of TriangleMesh related objects. The method is used to query the last intersected triangle, after a positive called to the doIntersection method. */ public int doIntersectionInformation() { return selectedTriangle; } /** Provides an object to text report convertion, optimized for human readability and debugging. Do not use for serialization or persistence purposes. */ public String toString() { String msg; int i; double mm[]; mm = getMinMax(); Vector3D p; msg = "- TriangleMesh ------------------------------------------------------------\n"; msg += " - Number of triangles:" + triangles.length + "\n"; msg += " - Number of vertexes:" + vertexes.length + "\n"; p = new Vector3D(mm[0], mm[1], mm[2]); msg += " - MINMAX: " + p; p = new Vector3D(mm[3], mm[4], mm[5]); msg += " - " + p + "\n"; if ( materials == null ) { msg += " - No materials available!\n"; } else { msg += " - " + materials.length + " materials\n"; } if ( materialRanges == null ) { msg += " - No material ranges association table available!\n"; } else { msg += " - " + materialRanges.length + " material spans:\n"; for ( i = 0; i < materialRanges.length; i++ ) { msg += " . " + materialRanges[i][0] + " -> " + materialRanges[i][1] + "\n"; } } if ( textures == null ) { msg += " - No textures available!\n"; } else { msg += " - " + textures.length + " textures\n"; } if ( textureRanges == null ) { msg += " - No texture ranges association table available!\n"; } else { msg += " - " + textureRanges.length + " texture spans:\n"; for ( i = 0; i < textureRanges.length; i++ ) { msg += " . " + textureRanges[i][0] + " -> " + textureRanges[i][1] + "\n"; } } msg += "---------------------------------------------------------------------------\n"; return msg; } /** Check the general interface contract in superclass method Geometry.doIntersection. */ public boolean doIntersection(Ray inOut_Ray) { int i; // Index for iterating triangles boolean intersection; // true if intersection founded double min_t; // Shortest distance founded so far Vector3D v0, v1, v2; // Positions of the three triangle points Vector3D p; // Point of intersection between ray and plane Vector3D n; // Normal at point of intersection Ray myRay = new Ray(inOut_Ray); // Bounding volume check if ( boundingVolume == null ) { double[] mm = getMinMax(); Vector3D size, center; size = new Vector3D(mm[3]-mm[0], mm[4]-mm[1], mm[5]-mm[2]); center = new Vector3D((mm[3]+mm[0])/2, (mm[4]+mm[1])/2, (mm[5]+mm[2])/2); boundingVolume = new SimpleBody(); boundingVolume.setPosition(center); boundingVolume.setGeometry(new Box(size)); } if ( !boundingVolume.doIntersection(inOut_Ray) ) { return false; } // Initialization values for search algorithm min_t = Double.MAX_VALUE; intersection = false; selectedTriangle = 0; p = new Vector3D(); n = new Vector3D(); // For each triangle in the mesh ... for ( i = 0; i < triangles.length; i++ ) { // The Triangle i has vertices <v0, v1, v2> v0 = vertexes[triangles[i].p0].position; v1 = vertexes[triangles[i].p1].position; v2 = vertexes[triangles[i].p2].position; if ( doIntersectionWithTriangle(myRay, v0, v1, v2, p, n) ) { if ( myRay.t < min_t ) { lastInfo.p = p; lastInfo.n = n; inOut_Ray.t = myRay.t; lastRay = inOut_Ray; min_t = myRay.t; selectedTriangle = i; intersection = true; } } } return intersection; } /** Check the general interface contract in superclass method Geometry.doExtraInformation. */ public void doExtraInformation(Ray inRay, double inT, GeometryIntersectionInformation outData) { //----------------------------------------------------------------- Vector3D p0, p1, p2; // Positions of the three triangle points Vector3D n0, n1, n2; // Normals of the three triangle points double u0, v0, u1, v1, u2, v2; // Texture coordinates //if ( withInterpolation ) { p0 = vertexes[triangles[selectedTriangle].p0].position; p1 = vertexes[triangles[selectedTriangle].p1].position; p2 = vertexes[triangles[selectedTriangle].p2].position; // Obtain barycentric coordinates for point p // Method taken from wikipedia double A, B, C, D, E, F, G, H, I; double lambda0, lambda1, lambda2; A = p0.x - p2.x; B = p1.x - p2.x; C = p2.x - lastInfo.p.x; D = p0.y - p2.y; E = p1.y - p2.y; F = p2.y - lastInfo.p.y; G = p0.z - p2.z; H = p1.z - p2.z; I = p2.z - lastInfo.p.z; // Point interpolation of three vertex positions lambda0 = (B*(F+I)-C*(E+H))/(A*(E+H)-B*(D+G)); lambda1 = (A*(F+I)-C*(D+G))/(B*(D+G)-A*(E+H)); lambda2 = 1-lambda0-lambda1; // Normal interpolation n0 = vertexes[triangles[selectedTriangle].p0].normal; n1 = vertexes[triangles[selectedTriangle].p1].normal; n2 = vertexes[triangles[selectedTriangle].p2].normal; lastInfo.n = n0.multiply(lambda0). add(n1.multiply(lambda1). add(n2.multiply(lambda2))); // Texture map coordinates interpolation u0 = vertexes[triangles[selectedTriangle].p0].u; v0 = vertexes[triangles[selectedTriangle].p0].v; u1 = vertexes[triangles[selectedTriangle].p1].u; v1 = vertexes[triangles[selectedTriangle].p1].v; u2 = vertexes[triangles[selectedTriangle].p2].u; v2 = vertexes[triangles[selectedTriangle].p2].v; lastInfo.u = u0*lambda0 + u1*lambda1 + u2*lambda2; lastInfo.v = v0*lambda0 + v1*lambda1 + v2*lambda2; //} lastInfo.n.normalize(); // Normal is always pointed "outwards" with respect to // the triangle (this manages the issue of back-facing // normals) if ( lastInfo.n.dotProduct(lastRay.direction) >= 0 ) { lastInfo.n = lastInfo.n.multiply(-1); } //----------------------------------------------------------------- outData.clone(lastInfo); //----------------------------------------------------------------- if ( materials != null ) { outData.material = materials[0]; } if ( materialRanges != null ) { for ( int i = 0; i < materialRanges.length-1 ; i++ ) { if ( selectedTriangle >= materialRanges[i][0] && selectedTriangle < materialRanges[i+1][0] ) { outData.material = materials[materialRanges[i+1][1]]; break; } } } outData.texture = null; if ( textureRanges != null ) { for ( int i = 0; i < textureRanges.length-1 ; i++ ) { if ( selectedTriangle >= textureRanges[i][0] && selectedTriangle < textureRanges[i+1][0] ) { outData.texture = textures[textureRanges[i+1][1]-1]; break; } } } } /** Check the general interface contract in superclass method Geometry.doContainmentTest. @todo Check efficiency for this implementation. Note that for the special application of volume rendering generation, it is better to provide another method, to add voxels after a path following over the line. */ public int doContainmentTest(Vector3D p, double distanceTolerance) { int i; int status; for ( i = 0; i < triangles.length; i++ ) { status = ComputationalGeometry.triangleContainmentTest( vertexes[triangles[i].p0].position, vertexes[triangles[i].p1].position, vertexes[triangles[i].p2].position, p, distanceTolerance); if ( status != OUTSIDE ) { return LIMIT; } } return OUTSIDE; } /** Check the general interface contract in superclass method Geometry.getMinMax. */ public double[] getMinMax() { if ( minMax == null ) { calculateMinMaxPositions(); } return minMax; } /** Check the general interface contract in superclass method Geometry.doVoxelization. Current method follows the voxelization algorithm strategy proposed in [DACH2000], but actual implementation only accounts for binary voxels. It is spected that with few changes, this algorithm manages the scalar (multivalued) voxel case for antialiased voxelization. */ public void doVoxelization(VoxelVolume vv, Matrix4x4 M, ProgressMonitor reporter) { // The `*Geom` variables are in geometry space Vector3D p0Geom, p1Geom, p2Geom; // The `*Volume` variables are in voxel space Vector3D p0Volume, p1Volume, p2Volume, minpVolume, maxpVolume, pVolume; // Voxel volume control int minI, minJ, minK; int maxI, maxJ, maxK; int i, j, k; // Structural algorithm control variables int t; int status; Matrix4x4 Minv = M.inverse(); double triangleMinmax[] = new double[6]; double distanceTolerance; minpVolume = new Vector3D(); maxpVolume = new Vector3D(); for ( t = 0; t < triangles.length; t++ ) { // Process i-th triangle in mesh p0Geom = vertexes[triangles[t].p0].position; p1Geom = vertexes[triangles[t].p1].position; p2Geom = vertexes[triangles[t].p2].position; // Obtain triangle in voxel coordinates p0Volume = Minv.multiply(p0Geom); p1Volume = Minv.multiply(p1Geom); p2Volume = Minv.multiply(p2Geom); // Obtain triangle minmax ComputationalGeometry.triangleMinMax(p0Volume, p1Volume, p2Volume, triangleMinmax); minpVolume.x = triangleMinmax[0]; minpVolume.y = triangleMinmax[1]; minpVolume.z = triangleMinmax[2]; maxpVolume.x = triangleMinmax[3]; maxpVolume.y = triangleMinmax[4]; maxpVolume.z = triangleMinmax[5]; minI = vv.getNearestIFromX(minpVolume.x); minJ = vv.getNearestJFromY(minpVolume.y); minK = vv.getNearestKFromZ(minpVolume.z); maxI = vv.getNearestIFromX(maxpVolume.x); maxJ = vv.getNearestJFromY(maxpVolume.y); maxK = vv.getNearestKFromZ(maxpVolume.z); // Rasterize triangle in voxel space distanceTolerance = 2.0 / (double)vv.getXSize(); for ( i = minI; i <= maxI; i++ ) { for ( j = minJ; j <= maxJ; j++ ) { for ( k = minK; k <= maxK; k++ ) { pVolume = vv.getVoxelPosition(i, j, k); status = ComputationalGeometry.triangleContainmentTest( p0Volume, p1Volume, p2Volume, pVolume, distanceTolerance); if ( status != OUTSIDE ) { vv.putVoxel(i, j, k, (byte)255); } } } } } } public TriangleMeshGroup exportToTriangleMeshGroup() { if ( triangleMeshGroupCache == null ) { triangleMeshGroupCache = new TriangleMeshGroup(); triangleMeshGroupCache.addMesh(this); } return triangleMeshGroupCache; }}//===========================================================================//= EOF =//===========================================================================
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -