// Mesh the area into nodes and elements or return error message if fails // assumes edges already oriented correctly const char *Area::MeshElements(void) { // exactly 2 paths will be for an interface if(numPaths==2) return MeshInterface(); // Must be 4-sided area. In future should support more if(numPaths!=4) return "Code can only mesh quadrilateral areas (4 paths) or interfaces (2 paths)."; // cannot be interface elements if(theElems->InterfaceElements()) return "Areas cannot be meshed into interface elements."; // must be connected if(edges[numPaths-1]->LastKeypoint()!=edges[0]->FirstKeypoint()) return "Area does not define enclosed area."; // is element provided if(theElems->CurrentElemID()<0) return "No element type defined for area."; // Check intervals if(!CheckIntervals()) return "Number of intervals on sides of the area are not valid"; // Check path usage if(!PathsAvailable()) return "Paths cannot be meshed into more than 2 areas"; // Check ccw if(SignedArea()<0.) return "The paths must circumnavigate the area in a counter-clockwise direction"; // create function if being used if(angleExpr!=NULL) { if(!CreateFunction(angleExpr)) return "The expression for material angle is not a valid function"; } // mesh the error return MeshArea(); }
void OcclusionBuffer::DrawTriangle(Vector4* vertices) { unsigned clipMask = 0; unsigned andClipMask = 0; bool drawOk = false; Vector3 projected[3]; // Build the clip plane mask for the triangle for (unsigned i = 0; i < 3; ++i) { unsigned vertexClipMask = 0; if (vertices[i].x_ > vertices[i].w_) vertexClipMask |= CLIPMASK_X_POS; if (vertices[i].x_ < -vertices[i].w_) vertexClipMask |= CLIPMASK_X_NEG; if (vertices[i].y_ > vertices[i].w_) vertexClipMask |= CLIPMASK_Y_POS; if (vertices[i].y_ < -vertices[i].w_) vertexClipMask |= CLIPMASK_Y_NEG; if (vertices[i].z_ > vertices[i].w_) vertexClipMask |= CLIPMASK_Z_POS; if (vertices[i].z_ < 0.0f) vertexClipMask |= CLIPMASK_Z_NEG; clipMask |= vertexClipMask; if (!i) andClipMask = vertexClipMask; else andClipMask &= vertexClipMask; } // If triangle is fully behind any clip plane, can reject quickly if (andClipMask) return; // Check if triangle is fully inside if (!clipMask) { projected[0] = ViewportTransform(vertices[0]); projected[1] = ViewportTransform(vertices[1]); projected[2] = ViewportTransform(vertices[2]); bool clockwise = SignedArea(projected[0], projected[1], projected[2]) < 0.0f; if (cullMode_ == CULL_NONE || (cullMode_ == CULL_CCW && clockwise) || (cullMode_ == CULL_CW && !clockwise)) { DrawTriangle2D(projected, clockwise); drawOk = true; } } else { bool triangles[64]; // Initial triangle triangles[0] = true; unsigned numTriangles = 1; if (clipMask & CLIPMASK_X_POS) ClipVertices(Vector4(-1.0f, 0.0f, 0.0f, 1.0f), vertices, triangles, numTriangles); if (clipMask & CLIPMASK_X_NEG) ClipVertices(Vector4(1.0f, 0.0f, 0.0f, 1.0f), vertices, triangles, numTriangles); if (clipMask & CLIPMASK_Y_POS) ClipVertices(Vector4(0.0f, -1.0f, 0.0f, 1.0f), vertices, triangles, numTriangles); if (clipMask & CLIPMASK_Y_NEG) ClipVertices(Vector4(0.0f, 1.0f, 0.0f, 1.0f), vertices, triangles, numTriangles); if (clipMask & CLIPMASK_Z_POS) ClipVertices(Vector4(0.0f, 0.0f, -1.0f, 1.0f), vertices, triangles, numTriangles); if (clipMask & CLIPMASK_Z_NEG) ClipVertices(Vector4(0.0f, 0.0f, 1.0f, 0.0f), vertices, triangles, numTriangles); // Draw each accepted triangle for (unsigned i = 0; i < numTriangles; ++i) { if (triangles[i]) { unsigned index = i * 3; projected[0] = ViewportTransform(vertices[index]); projected[1] = ViewportTransform(vertices[index + 1]); projected[2] = ViewportTransform(vertices[index + 2]); bool clockwise = SignedArea(projected[0], projected[1], projected[2]) < 0.0f; if (cullMode_ == CULL_NONE || (cullMode_ == CULL_CCW && clockwise) || (cullMode_ == CULL_CW && !clockwise)) { DrawTriangle2D(projected, clockwise); drawOk = true; } } } } if (drawOk) ++numTriangles_; }