//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void OutlineEdgeExtractor::addFaceList(const UIntArray& faceList) { size_t numFaceListEntries = faceList.size(); size_t i = 0; while (i < numFaceListEntries) { uint numVerticesInFace = faceList[i++]; CVF_ASSERT(numVerticesInFace > 0); CVF_ASSERT(i + numVerticesInFace <= numFaceListEntries); const uint* indexPtr = &faceList[i]; addPrimitives(numVerticesInFace, indexPtr, numVerticesInFace); i += numVerticesInFace; } }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- TEST(PrimitiveSetIndexedUInt, GetOpenGLPrimitive_FromLineLoop) { ref<UIntArray> indices = new UIntArray; indices->reserve(4); indices->add(0); indices->add(1); indices->add(2); indices->add(3); ref<PrimitiveSetIndexedUInt> myPrim = new PrimitiveSetIndexedUInt(PT_LINE_LOOP); myPrim->setIndices(indices.p()); ASSERT_EQ(4u, myPrim->faceCount()); UIntArray conn; myPrim->getFaceIndices(0, &conn); ASSERT_EQ(2u, conn.size()); EXPECT_EQ(0u, conn.get(0)); EXPECT_EQ(1u, conn.get(1)); myPrim->getFaceIndices(1, &conn); ASSERT_EQ(2u, conn.size()); EXPECT_EQ(1u, conn.get(0)); EXPECT_EQ(2u, conn.get(1)); myPrim->getFaceIndices(2, &conn); ASSERT_EQ(2u, conn.size()); EXPECT_EQ(2u, conn.get(0)); EXPECT_EQ(3u, conn.get(1)); myPrim->getFaceIndices(3, &conn); ASSERT_EQ(2u, conn.size()); EXPECT_EQ(3u, conn.get(0)); EXPECT_EQ(0u, conn.get(1)); }
//-------------------------------------------------------------------------------------------------- /// Add a triangle strip /// /// Vertex ordering for triangle strips: /// <PRE> /// v0 v2 v4 Resulting triangles: /// *-------*-------* t1: v0, v1, v2 /// \ / \ / \ t2: v2, v1, v3 /// \ / \ / \ t3: v2, v3, v4 /// \ / \ / \ t4: v4, v3, v5 /// *-------*-------* /// v1 v3 v5 </PRE> /// /// \remarks The number of entries in the \a indices array must be at least 3. //-------------------------------------------------------------------------------------------------- void GeometryBuilder::addTriangleStrip(const UIntArray& indices) { size_t numIndices = indices.size(); CVF_ASSERT(numIndices >= 3); size_t numTriangles = numIndices - 2; CVF_ASSERT(numTriangles >= 1); size_t i; for (i = 0; i < numTriangles; i++) { if (i % 2 == 0) { addTriangle(indices[i], indices[i + 1], indices[i + 2]); } else { addTriangle(indices[i + 1], indices[i], indices[i + 2]); } } }
//-------------------------------------------------------------------------------------------------- /// Add one face /// /// The type of primitive added will be determined from the number of indices passed in \a indices /// /// \remarks Currently, points and lines are not supported. Faces with more than 4 indices will /// be triangulated using fanning //-------------------------------------------------------------------------------------------------- void GeometryBuilder::addFace(const UIntArray& indices) { size_t numIndices = indices.size(); CVF_ASSERT(numIndices >= 3); if (numIndices == 3) { addTriangle(indices[0], indices[1], indices[2]); } else if (numIndices == 4) { addQuad(indices[0], indices[1], indices[2], indices[3]); } else { size_t numTriangles = numIndices - 2; size_t i; for (i = 0; i < numTriangles; i++) { addTriangle(indices[0], indices[i + 1], indices[i + 2]); } } }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- TEST(MeshEdgeExtractorTest, ThreeQuadsFromUIntArray) { // 3------4------5 9------8 // | | | | | // | | | | | // 0------1------2 6------7 MeshEdgeExtractor ee; // Two connected quads { UIntArray q; q.reserve(2*4); // Observe different winding q.add(0); q.add(1); q.add(4); q.add(3); q.add(1); q.add(4); q.add(5); q.add(2); ee.addPrimitives(4, q); } // Single loose quad { UIntArray q; q.reserve(4); q.add(6); q.add(7); q.add(8); q.add(9); ee.addPrimitives(4, q); } ref<UIntArray> li = ee.lineIndices(); ASSERT_EQ(2*11, li->size()); EXPECT_EQ(0, li->get(0)); EXPECT_EQ(1, li->get(1)); EXPECT_EQ(0, li->get(2)); EXPECT_EQ(3, li->get(3)); EXPECT_EQ(1, li->get(4)); EXPECT_EQ(2, li->get(5)); EXPECT_EQ(1, li->get(6)); EXPECT_EQ(4, li->get(7)); EXPECT_EQ(2, li->get(8)); EXPECT_EQ(5, li->get(9)); EXPECT_EQ(3, li->get(10)); EXPECT_EQ(4, li->get(11)); EXPECT_EQ(4, li->get(12)); EXPECT_EQ(5, li->get(13)); EXPECT_EQ(6, li->get(14)); EXPECT_EQ(7, li->get(15)); EXPECT_EQ(6, li->get(16)); EXPECT_EQ(9, li->get(17)); EXPECT_EQ(7, li->get(18)); EXPECT_EQ(8, li->get(19)); EXPECT_EQ(8, li->get(20)); EXPECT_EQ(9, li->get(21)); }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- TEST(MeshEdgeExtractorTest, PrimitiveMixFromFaceList) { // 6----5 // / \ *11 // / \ *12 // 8------7 4-----9 // | |\ / | // | | \ / | // 0------1--2----3 10 UIntArray fl; fl.reserve(26); fl.add(1); fl.add(11); fl.add(1); fl.add(12); fl.add(2); fl.add(4); fl.add(9); fl.add(2); fl.add(10); fl.add(9); fl.add(3); fl.add(1); fl.add(2); fl.add(7); fl.add(4); fl.add(0); fl.add(1); fl.add(7); fl.add(8); fl.add(6); fl.add(2); fl.add(3); fl.add(4); fl.add(5); fl.add(6); fl.add(7); ASSERT_EQ(26, fl.size()); MeshEdgeExtractor ee; ee.addFaceList(fl); UIntArray li = *ee.lineIndices(); ASSERT_EQ(2*13, li.size()); EXPECT_EQ(0, li[ 0]); EXPECT_EQ(1, li[ 1]); EXPECT_EQ(0, li[ 2]); EXPECT_EQ(8, li[ 3]); EXPECT_EQ(1, li[ 4]); EXPECT_EQ(2, li[ 5]); EXPECT_EQ(1, li[ 6]); EXPECT_EQ(7, li[ 7]); EXPECT_EQ(2, li[ 8]); EXPECT_EQ(3, li[ 9]); EXPECT_EQ(2, li[10]); EXPECT_EQ(7, li[11]); EXPECT_EQ(3, li[12]); EXPECT_EQ(4, li[13]); EXPECT_EQ(4, li[14]); EXPECT_EQ(5, li[15]); EXPECT_EQ(4, li[16]); EXPECT_EQ(9, li[17]); EXPECT_EQ(5, li[18]); EXPECT_EQ(6, li[19]); EXPECT_EQ(6, li[20]); EXPECT_EQ(7, li[21]); EXPECT_EQ(7, li[22]); EXPECT_EQ(8, li[23]); EXPECT_EQ(9, li[24]); EXPECT_EQ(10,li[25]); }
Array* Array_readLocalData(Input& fr) { if (fr[0].matchWord("Use")) { if (fr[1].isString()) { Object* obj = fr.getObjectForUniqueID(fr[1].getStr()); if (obj) { fr+=2; return dynamic_cast<Array*>(obj); } } osg::notify(osg::WARN)<<"Warning: invalid uniqueID found in file."<<std::endl; return NULL; } std::string uniqueID; if (fr[0].matchWord("UniqueID") && fr[1].isString()) { uniqueID = fr[1].getStr(); fr += 2; } int entry = fr[0].getNoNestedBrackets(); const char* arrayName = fr[0].getStr(); unsigned int capacity = 0; fr[1].getUInt(capacity); ++fr; fr += 2; Array* return_array = 0; if (strcmp(arrayName,"ByteArray")==0) { ByteArray* array = new ByteArray; array->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { int int_value; if (fr[0].getInt(int_value)) { ++fr; array->push_back(int_value); } else ++fr; } ++fr; return_array = array; } else if (strcmp(arrayName,"ShortArray")==0) { ShortArray* array = new ShortArray; array->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { int int_value; if (fr[0].getInt(int_value)) { ++fr; array->push_back(int_value); } else ++fr; } ++fr; return_array = array; } else if (strcmp(arrayName,"IntArray")==0) { IntArray* array = new IntArray; array->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { int int_value; if (fr[0].getInt(int_value)) { ++fr; array->push_back(int_value); } else ++fr; } ++fr; return_array = array; } else if (strcmp(arrayName,"UByteArray")==0) { UByteArray* array = new UByteArray; array->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { unsigned int uint_value; if (fr[0].getUInt(uint_value)) { ++fr; array->push_back(uint_value); } else ++fr; } ++fr; return_array = array; } else if (strcmp(arrayName,"UShortArray")==0) { UShortArray* array = new UShortArray; array->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { unsigned int uint_value; if (fr[0].getUInt(uint_value)) { ++fr; array->push_back(uint_value); } else ++fr; } ++fr; return_array = array; } else if (strcmp(arrayName,"UIntArray")==0) { UIntArray* array = new UIntArray; array->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { unsigned int uint_value; if (fr[0].getUInt(uint_value)) { ++fr; array->push_back(uint_value); } else ++fr; } ++fr; return_array = array; } else if (strcmp(arrayName,"UVec4bArray")==0 || strcmp(arrayName,"Vec4ubArray")==0) { Vec4ubArray* array = new Vec4ubArray; array->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { unsigned int r,g,b,a; if (fr[0].getUInt(r) && fr[1].getUInt(g) && fr[2].getUInt(b) && fr[3].getUInt(a)) { fr+=4; array->push_back(osg::Vec4ub(r,g,b,a)); } else ++fr; } ++fr; return_array = array; } else if (strcmp(arrayName,"FloatArray")==0) { FloatArray* array = new FloatArray; array->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { float float_value; if (fr[0].getFloat(float_value)) { ++fr; array->push_back(float_value); } else ++fr; } ++fr; return_array = array; } else if (strcmp(arrayName,"DoubleArray")==0) { DoubleArray* array = new DoubleArray; array->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { double double_value; if (fr[0].getFloat(double_value)) { ++fr; array->push_back(double_value); } else ++fr; } ++fr; return_array = array; } else if (strcmp(arrayName,"Vec2Array")==0) { Vec2Array* array = new Vec2Array; array->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { Vec2 v; if (fr[0].getFloat(v.x()) && fr[1].getFloat(v.y())) { fr += 2; array->push_back(v); } else ++fr; } ++fr; return_array = array; } else if (strcmp(arrayName,"Vec2dArray")==0) { Vec2dArray* array = new Vec2dArray; array->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { Vec2d v; if (fr[0].getFloat(v.x()) && fr[1].getFloat(v.y())) { fr += 2; array->push_back(v); } else ++fr; } ++fr; return_array = array; } else if (strcmp(arrayName,"Vec3Array")==0) { Vec3Array* array = new Vec3Array; array->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { Vec3 v; if (fr[0].getFloat(v.x()) && fr[1].getFloat(v.y()) && fr[2].getFloat(v.z())) { fr += 3; array->push_back(v); } else ++fr; } ++fr; return_array = array; } else if (strcmp(arrayName,"Vec3dArray")==0) { Vec3dArray* array = new Vec3dArray; array->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { Vec3d v; if (fr[0].getFloat(v.x()) && fr[1].getFloat(v.y()) && fr[2].getFloat(v.z())) { fr += 3; array->push_back(v); } else ++fr; } ++fr; return_array = array; } else if (strcmp(arrayName,"Vec4Array")==0) { Vec4Array* array = new Vec4Array; array->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { Vec4 v; if (fr[0].getFloat(v.x()) && fr[1].getFloat(v.y()) && fr[2].getFloat(v.z()) && fr[3].getFloat(v.w())) { fr += 4; array->push_back(v); } else ++fr; } ++fr; return_array = array; } else if (strcmp(arrayName,"Vec4dArray")==0) { Vec4dArray* array = new Vec4dArray; array->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { Vec4d v; if (fr[0].getFloat(v.x()) && fr[1].getFloat(v.y()) && fr[2].getFloat(v.z()) && fr[3].getFloat(v.w())) { fr += 4; array->push_back(v); } else ++fr; } ++fr; return_array = array; } else if (strcmp(arrayName,"Vec2bArray")==0) { Vec2bArray* array = new Vec2bArray; array->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { unsigned int r,g; if (fr[0].getUInt(r) && fr[1].getUInt(g)) { fr+=2; array->push_back(osg::Vec2b(r,g)); } else ++fr; } ++fr; return_array = array; } else if (strcmp(arrayName,"Vec3bArray")==0) { Vec3bArray* array = new Vec3bArray; array->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { unsigned int r,g,b; if (fr[0].getUInt(r) && fr[1].getUInt(g) && fr[2].getUInt(b)) { fr+=3; array->push_back(osg::Vec3b(r,g,b)); } else ++fr; } ++fr; return_array = array; } else if (strcmp(arrayName,"Vec4bArray")==0) { Vec4bArray* array = new Vec4bArray; array->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { unsigned int r,g,b,a; if (fr[0].getUInt(r) && fr[1].getUInt(g) && fr[2].getUInt(b) && fr[3].getUInt(a)) { fr+=4; array->push_back(osg::Vec4b(r,g,b,a)); } else ++fr; } ++fr; return_array = array; } else if (strcmp(arrayName,"Vec2sArray")==0) { Vec2sArray* array = new Vec2sArray; array->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { unsigned int r,g; if (fr[0].getUInt(r) && fr[1].getUInt(g)) { fr+=2; array->push_back(osg::Vec2s(r,g)); } else ++fr; } ++fr; return_array = array; } else if (strcmp(arrayName,"Vec3sArray")==0) { Vec3sArray* array = new Vec3sArray; array->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { unsigned int r,g,b; if (fr[0].getUInt(r) && fr[1].getUInt(g) && fr[2].getUInt(b)) { fr+=3; array->push_back(osg::Vec3s(r,g,b)); } else ++fr; } ++fr; return_array = array; } else if (strcmp(arrayName,"Vec4sArray")==0) { Vec4sArray* array = new Vec4sArray; array->reserve(capacity); while (!fr.eof() && fr[0].getNoNestedBrackets()>entry) { unsigned int r,g,b,a; if (fr[0].getUInt(r) && fr[1].getUInt(g) && fr[2].getUInt(b) && fr[3].getUInt(a)) { fr+=4; array->push_back(osg::Vec4s(r,g,b,a)); } else ++fr; } ++fr; return_array = array; } if (return_array) { if (!uniqueID.empty()) fr.registerUniqueIDForObject(uniqueID.c_str(),return_array); } return return_array; }
//-------------------------------------------------------------------------------------------------- /// Sets the DrawableGeo object's geometry representation from a face list /// /// \param faceList Face list /// /// faceList contains number of items before each face connectivities. E.g. 3 0 1 2 3 2 3 1 3 2 1 3 /// /// \note This method will use more temporary memory than strictly needed in order to optimize /// performance. //-------------------------------------------------------------------------------------------------- void DrawableGeo::setFromFaceList(const UIntArray& faceList) { m_primitiveSets.clear(); size_t numFaceListEntries = faceList.size(); ref<UIntArray> triangleConnects = new UIntArray; triangleConnects->reserve(numFaceListEntries*3); // Usually too much, but temporary and will be squeezed if kept. size_t i = 0; while (i < numFaceListEntries) { uint numConnects = faceList[i++]; CVF_ASSERT(numConnects >= 3); if (numConnects == 3) { triangleConnects->add(faceList[i++]); triangleConnects->add(faceList[i++]); triangleConnects->add(faceList[i++]); } else { size_t j; for (j = 0; j < numConnects - 2; j++) { triangleConnects->add(faceList[i]); triangleConnects->add(faceList[i + 1 + j]); triangleConnects->add(faceList[i + 2 + j]); } i += numConnects; } } // Check if the largest index used in the triangle connects exceeds short representation if (triangleConnects->max() < std::numeric_limits<ushort>::max()) { // Create an USHORT primitive set size_t arraySize = triangleConnects->size(); ref<UShortArray> shortIndices = new UShortArray; shortIndices->resize(arraySize); size_t j; for (j = 0; j < arraySize; j++) { shortIndices->set(j, static_cast<ushort>(triangleConnects->get(j))); } ref<PrimitiveSetIndexedUShort> prim = new PrimitiveSetIndexedUShort(PT_TRIANGLES); prim->setIndices(shortIndices.p()); m_primitiveSets.push_back(prim.p()); } else { // Create a UINT primitive set ref<PrimitiveSetIndexedUInt> prim = new PrimitiveSetIndexedUInt(PT_TRIANGLES); triangleConnects->squeeze(); prim->setIndices(triangleConnects.p()); m_primitiveSets.push_back(prim.p()); } }
//-------------------------------------------------------------------------------------------------- /// Intersect the drawable geo with the ray and return the closest intersection point and the face hit /// /// Returns true if anything was hit. //-------------------------------------------------------------------------------------------------- bool DrawableGeo::rayIntersect(const Ray& ray, Vec3d* intersectionPoint, uint* faceHit) const { CVF_ASSERT(intersectionPoint); bool anyHits = false; double minDistSquared = 1.0e300; cref<Vec3fArray> vertexArr = m_vertexBundle->vertexArray(); size_t numPrimitiveSets = m_primitiveSets.size(); size_t iPrimSet; int accumulatedFaceCount = 0; for (iPrimSet = 0; iPrimSet < numPrimitiveSets; iPrimSet++) { const PrimitiveSet* primSet = m_primitiveSets.at(iPrimSet); CVF_TIGHT_ASSERT(primSet); UIntArray conn; int numPrimFaces = static_cast<int>(primSet->faceCount()); #pragma omp parallel for private (conn) for (int i = 0; i < numPrimFaces; i++) { bool hitThisFace = false; Vec3d localIntersect; primSet->getFaceIndices(static_cast<size_t>(i), &conn); int numconn = static_cast<int>(conn.size()); CVF_TIGHT_ASSERT(numconn <= 3); if (numconn == 3) { hitThisFace = ray.triangleIntersect(Vec3d(vertexArr->get(conn[0])), Vec3d(vertexArr->get(conn[1])), Vec3d(vertexArr->get(conn[2])), &localIntersect); } if (hitThisFace) { double distSquared = (ray.origin() - localIntersect).lengthSquared(); #pragma omp critical { if (distSquared < minDistSquared) { *intersectionPoint = localIntersect; minDistSquared = distSquared; if (faceHit) { *faceHit = i + accumulatedFaceCount; } } anyHits = true; } } } // End omp parallel for accumulatedFaceCount += numPrimFaces; } return anyHits; }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- TEST(PrimitiveSetIndexedUInt, GetOpenGLPrimitive_FromTriStrip) { // See TEST(GeometryBuilderTest, AddTriangleStrip) ref<UIntArray> indices = new UIntArray; indices->reserve(6); indices->add(0); indices->add(1); indices->add(2); indices->add(3); indices->add(4); indices->add(5); ref<PrimitiveSetIndexedUInt> myPrim = new PrimitiveSetIndexedUInt(PT_TRIANGLE_STRIP); myPrim->setIndices(indices.p()); ASSERT_EQ(4u, myPrim->faceCount()); UIntArray conn; myPrim->getFaceIndices(0, &conn); ASSERT_EQ(3u, conn.size()); EXPECT_EQ(0u, conn.get(0)); EXPECT_EQ(1u, conn.get(1)); EXPECT_EQ(2u, conn.get(2)); myPrim->getFaceIndices(1, &conn); ASSERT_EQ(3u, conn.size()); EXPECT_EQ(2u, conn.get(0)); EXPECT_EQ(1u, conn.get(1)); EXPECT_EQ(3u, conn.get(2)); myPrim->getFaceIndices(2, &conn); ASSERT_EQ(3u, conn.size()); EXPECT_EQ(2u, conn.get(0)); EXPECT_EQ(3u, conn.get(1)); EXPECT_EQ(4u, conn.get(2)); myPrim->getFaceIndices(3, &conn); ASSERT_EQ(3u, conn.size()); EXPECT_EQ(4u, conn.get(0)); EXPECT_EQ(3u, conn.get(1)); EXPECT_EQ(5u, conn.get(2)); }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- TEST(OutlineEdgeExtractorTest, SinglePrimitives) { ref<Vec3fArray> va = new Vec3fArray; va->reserve(4); va->add(Vec3f(0, 0, 0)); va->add(Vec3f(1, 0, 0)); va->add(Vec3f(1, 1, 0)); va->add(Vec3f(0, 1, 0)); // Point { const cvf::uint conn[1] = { 0 }; OutlineEdgeExtractor ee(0, *va); ee.addPrimitives(1, conn, 1); UIntArray li = *ee.lineIndices(); ASSERT_EQ(0, li.size()); } // Line { const cvf::uint conn[2] = { 0, 1 }; OutlineEdgeExtractor ee(0, *va); ee.addPrimitives(2, conn, 2); UIntArray li = *ee.lineIndices(); ASSERT_EQ(2, li.size()); ASSERT_EQ(0, li[0]); ASSERT_EQ(1, li[1]); } // Tri { const cvf::uint conn[3] = { 0, 1, 2 }; OutlineEdgeExtractor ee(0, *va); ee.addPrimitives(3, conn, 3); UIntArray li = *ee.lineIndices(); ASSERT_EQ(6, li.size()); ASSERT_EQ(0, li[0]); ASSERT_EQ(1, li[1]); ASSERT_EQ(0, li[2]); ASSERT_EQ(2, li[3]); ASSERT_EQ(1, li[4]); ASSERT_EQ(2, li[5]); } // Quad { const cvf::uint conn[4] = { 0, 1, 2, 3}; OutlineEdgeExtractor ee(0, *va); ee.addPrimitives(4, conn, 4); UIntArray li = *ee.lineIndices(); ASSERT_EQ(8, li.size()); ASSERT_EQ(0, li[0]); ASSERT_EQ(1, li[1]); ASSERT_EQ(0, li[2]); ASSERT_EQ(3, li[3]); ASSERT_EQ(1, li[4]); ASSERT_EQ(2, li[5]); ASSERT_EQ(2, li[6]); ASSERT_EQ(3, li[7]); } }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- TEST(OutlineEdgeExtractorTest, PrimitiveMixFromFaceList) { ref<Vec3fArray> va = new Vec3fArray; va->resize(13); va->set( 0, Vec3f(0, 0, 0)); va->set( 1, Vec3f(1, 0, 0)); va->set( 2, Vec3f(2, 0, 0)); va->set( 3, Vec3f(3, 0, 0)); va->set( 4, Vec3f(4, 1, 0)); va->set( 5, Vec3f(3, 2, 0)); va->set( 6, Vec3f(2, 2, 0)); va->set( 7, Vec3f(1, 1, 0)); va->set( 8, Vec3f(0, 1, 0)); va->set( 9, Vec3f(5, 1, 0)); va->set(10, Vec3f(5, 0, 0)); va->set(11, Vec3f(6, 6, 0)); va->set(12, Vec3f(7, 7, 0)); // // *11 // *12 // 8------7 4-----9 // | |\ | // | | \ | // 0------1--2 10 UIntArray fl; fl.reserve(26); fl.add(1); fl.add(11); fl.add(1); fl.add(12); fl.add(2); fl.add(4); fl.add(9); fl.add(2); fl.add(10); fl.add(9); fl.add(3); fl.add(1); fl.add(2); fl.add(7); fl.add(4); fl.add(0); fl.add(1); fl.add(7); fl.add(8); ASSERT_EQ(19, fl.size()); OutlineEdgeExtractor ee(0, *va); ee.addFaceList(fl); UIntArray li = *ee.lineIndices(); ASSERT_EQ(2*7, li.size()); EXPECT_TRUE( EdgeKey(0, 1) == EdgeKey(li[ 0], li[ 1]) ); EXPECT_TRUE( EdgeKey(0, 8) == EdgeKey(li[ 2], li[ 3]) ); EXPECT_TRUE( EdgeKey(1, 2) == EdgeKey(li[ 4], li[ 5]) ); EXPECT_TRUE( EdgeKey(2, 7) == EdgeKey(li[ 6], li[ 7]) ); EXPECT_TRUE( EdgeKey(4, 9) == EdgeKey(li[ 8], li[ 9]) ); EXPECT_TRUE( EdgeKey(7, 8) == EdgeKey(li[10], li[11]) ); EXPECT_TRUE( EdgeKey(9,10) == EdgeKey(li[12], li[13]) ); /* // 6----5 // / \ *11 // / \ *12 // 8------7 4-----9 // | |\ / | // | | \ / | // 0------1--2----3 10 fl.add(1); fl.add(11); fl.add(1); fl.add(12); fl.add(2); fl.add(4); fl.add(9); fl.add(2); fl.add(10); fl.add(9); fl.add(3); fl.add(1); fl.add(2); fl.add(7); fl.add(4); fl.add(0); fl.add(1); fl.add(7); fl.add(8); fl.add(6); fl.add(2); fl.add(3); fl.add(4); fl.add(5); fl.add(6); fl.add(7); ASSERT_EQ(26, fl.size()); OutlineEdgeExtractor ee(0, *va); ee.addFaceList(fl); UIntArray li = *ee.lineIndices(); ASSERT_EQ(2*11, li.size()); EXPECT_TRUE( EdgeKey(0, 1) == EdgeKey(li[ 0], li[ 1]) ); EXPECT_TRUE( EdgeKey(0, 8) == EdgeKey(li[ 2], li[ 3]) ); EXPECT_TRUE( EdgeKey(1, 2) == EdgeKey(li[ 4], li[ 5]) ); EXPECT_TRUE( EdgeKey(2, 3) == EdgeKey(li[ 6], li[ 7]) ); EXPECT_TRUE( EdgeKey(3, 4) == EdgeKey(li[ 8], li[ 9]) ); EXPECT_TRUE( EdgeKey(4, 5) == EdgeKey(li[10], li[11]) ); EXPECT_TRUE( EdgeKey(4, 9) == EdgeKey(li[12], li[13]) ); EXPECT_TRUE( EdgeKey(5, 6) == EdgeKey(li[14], li[15]) ); EXPECT_TRUE( EdgeKey(6, 7) == EdgeKey(li[16], li[17]) ); EXPECT_TRUE( EdgeKey(7, 8) == EdgeKey(li[18], li[19]) ); EXPECT_TRUE( EdgeKey(9,10) == EdgeKey(li[20], li[21]) ); */ }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- TEST(OutlineEdgeExtractorTest, CollapsedPrimitives) { ref<Vec3fArray> va = new Vec3fArray; va->reserve(4); va->add(Vec3f(0, 0, 0)); va->add(Vec3f(1, 0, 0)); va->add(Vec3f(1, 1, 0)); // Collapsed tris { const cvf::uint conn[3] = { 0, 1, 0 }; OutlineEdgeExtractor ee(0, *va); ee.addPrimitives(3, conn, 3); UIntArray li = *ee.lineIndices(); ASSERT_EQ(2, li.size()); EXPECT_EQ(0, li[0]); EXPECT_EQ(1, li[1]); } { const cvf::uint conn[3] = { 0, 0, 1 }; OutlineEdgeExtractor ee(0, *va); ee.addPrimitives(3, conn, 3); UIntArray li = *ee.lineIndices(); ASSERT_EQ(2, li.size()); EXPECT_EQ(0, li[0]); EXPECT_EQ(1, li[1]); } { const cvf::uint conn[3] = { 1, 1, 1 }; OutlineEdgeExtractor ee(0, *va); ee.addPrimitives(3, conn, 3); UIntArray li = *ee.lineIndices(); EXPECT_EQ(0, li.size()); } // Collapsed quads { const cvf::uint conn[4] = { 0, 1, 1, 2}; OutlineEdgeExtractor ee(0, *va); ee.addPrimitives(4, conn, 4); UIntArray li = *ee.lineIndices(); ASSERT_EQ(6, li.size()); EXPECT_EQ(0, li[0]); EXPECT_EQ(1, li[1]); EXPECT_EQ(0, li[2]); EXPECT_EQ(2, li[3]); EXPECT_EQ(1, li[4]); EXPECT_EQ(2, li[5]); } { const cvf::uint conn[4] = { 0, 1, 2, 0}; OutlineEdgeExtractor ee(0, *va); ee.addPrimitives(4, conn, 4); UIntArray li = *ee.lineIndices(); ASSERT_EQ(6, li.size()); EXPECT_EQ(0, li[0]); EXPECT_EQ(1, li[1]); EXPECT_EQ(0, li[2]); EXPECT_EQ(2, li[3]); EXPECT_EQ(1, li[4]); EXPECT_EQ(2, li[5]); } { const cvf::uint conn[4] = { 0, 1, 0, 1}; OutlineEdgeExtractor ee(0, *va); ee.addPrimitives(4, conn, 4); UIntArray li = *ee.lineIndices(); ASSERT_EQ(2, li.size()); EXPECT_EQ(0, li[0]); EXPECT_EQ(1, li[1]); } { const cvf::uint conn[4] = { 1, 1, 0, 1}; OutlineEdgeExtractor ee(0, *va); ee.addPrimitives(4, conn, 4); UIntArray li = *ee.lineIndices(); ASSERT_EQ(2, li.size()); EXPECT_EQ(0, li[0]); EXPECT_EQ(1, li[1]); } { const cvf::uint conn[4] = { 2, 2, 2, 2}; OutlineEdgeExtractor ee(0, *va); ee.addPrimitives(4, conn, 4); UIntArray li = *ee.lineIndices(); EXPECT_EQ(0, li.size()); } }