//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- TEST(PrimitiveSetIndexedUInt, GetOpenGLPrimitive_FromTriangles) { 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_TRIANGLES); myPrim->setIndices(indices.p()); ASSERT_EQ(2u, 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(3u, conn.get(0)); EXPECT_EQ(4u, conn.get(1)); EXPECT_EQ(5u, conn.get(2)); }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- TEST(PrimitiveSetIndexedUInt, GetOpenGLPrimitive_FromLineStrip) { 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_STRIP); myPrim->setIndices(indices.p()); ASSERT_EQ(3u, 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)); }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- bool DrawableGeo::rayIntersect(const Ray& ray, Vec3dArray* intersectionPoints, UIntArray* facesHit) const { if (intersectionPoints) intersectionPoints->setSizeZero(); if (facesHit) facesHit->setSizeZero(); std::vector<Vec3d> isectPts; std::vector<uint> faceIndices; cref<Vec3fArray> vertexArr = m_vertexBundle->vertexArray(); int accumulatedFaceCount = 0; size_t numPrimitiveSets = m_primitiveSets.size(); size_t iPrimSet; 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()); if (numconn == 3) { hitThisFace = ray.triangleIntersect(Vec3d(vertexArr->get(conn[0])), Vec3d(vertexArr->get(conn[1])), Vec3d(vertexArr->get(conn[2])), &localIntersect); } if (hitThisFace) { #pragma omp critical { isectPts.push_back(localIntersect); faceIndices.push_back(i + accumulatedFaceCount); } } } accumulatedFaceCount += numPrimFaces; } if (isectPts.size() > 0) { if (intersectionPoints) intersectionPoints->assign(isectPts); if (facesHit) facesHit->assign(faceIndices); return true; } else { return false; } }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- TEST(ArrayTest, setConsecutiveEmpty) { UIntArray arr; arr.setConsecutive(0); EXPECT_EQ(0, arr.size()); }
Beagle::MPI::GA::EvolverBitString::EvolverBitString(UIntArray inInitSize) { if(inInitSize.size()==0) addOperator(new Beagle::GA::InitBitStrOp(0)); else if(inInitSize.size()==1) addOperator(new Beagle::GA::InitBitStrOp(inInitSize[0])); else { std::ostringstream lOSS; lOSS << "Initialization of bit string individuals with more than one bit string "; lOSS << "is no more valid. You should use individuals made of one bit string, or "; lOSS << "define your own bit string initialization operator."; throw Beagle_RunTimeExceptionM(lOSS.str()); } addOperator(new Beagle::GA::CrossoverOnePointBitStrOp); addOperator(new Beagle::GA::CrossoverTwoPointsBitStrOp); addOperator(new Beagle::GA::CrossoverUniformBitStrOp); addOperator(new Beagle::GA::MutationFlipBitStrOp); }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- 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]); }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- 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)); }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- void OutlineEdgeExtractor::addPrimitives(uint verticesPerPrimitive, const UIntArray& indices) { CVF_ASSERT(verticesPerPrimitive > 0); size_t indexCount = indices.size(); size_t numPrimitives = indexCount/verticesPerPrimitive; if (numPrimitives > 0) { const uint* indexPtr = indices.ptr(); addPrimitives(verticesPerPrimitive, indexPtr, indexCount); } }
//-------------------------------------------------------------------------------------------------- /// Add a triangle fan /// /// Vertex ordering for triangle fans: /// <PRE> /// v4 *-------* v3 Resulting triangles: /// \ / \ t1: v0, v1, v2 /// \ / \ t2: v0, v2, v3 /// \ / \ t3: v0, v3, v4 /// v0 *-------* v2 /// \ / /// \ / /// \ / /// * v1 </PRE> /// /// \remarks The number of entries in the \a indices array must be at least 3. //-------------------------------------------------------------------------------------------------- void GeometryBuilder::addTriangleFan(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++) { addTriangle(indices[0], indices[i + 1], indices[i + 2]); } }
/*! * \brief Construct a GA Generational evolver. * \param inEvalOp Evaluation operator. * \param inInitSize Size of the GA bit strings. * \deprecated Use EvolverBitString(EvaluationOp::Handle,unsigned int) constructor instead. * \throw Beagle::RunTimeException If init size vector has more than one value. */ Beagle::MPI::GA::EvolverBitString::EvolverBitString(EvaluationOp::Handle inEvalOp, UIntArray inInitSize) : Beagle::MPI::Evolver(inEvalOp) { addOperator(inEvalOp); if(inInitSize.size()==0) addOperator(new Beagle::GA::InitBitStrOp(0)); else if(inInitSize.size()==1) addOperator(new Beagle::GA::InitBitStrOp(inInitSize[0])); else { std::ostringstream lOSS; lOSS << "Initialization of bit string individuals with more than one bit string "; lOSS << "is no more valid. You should use individuals made of one bit string, or "; lOSS << "define your own bit string initialization operator."; throw Beagle_RunTimeExceptionM(lOSS.str()); } addOperator(new Beagle::GA::CrossoverOnePointBitStrOp); addOperator(new Beagle::GA::CrossoverTwoPointsBitStrOp); addOperator(new Beagle::GA::CrossoverUniformBitStrOp); addOperator(new Beagle::GA::MutationFlipBitStrOp); addBootStrapOp("IfThenElseOp"); IfThenElseOp::Handle lITE = castHandleT<IfThenElseOp>(getBootStrapSet().back()); lITE->setConditionTag("ms.restart.file"); lITE->setConditionValue(""); lITE->insertPositiveOp("GA-InitBitStrOp", getOperatorMap()); lITE->insertPositiveOp(inEvalOp->getName(), getOperatorMap()); lITE->insertPositiveOp("StatsCalcFitnessSimpleOp", getOperatorMap()); lITE->insertNegativeOp("MilestoneReadOp", getOperatorMap()); addBootStrapOp("TermMaxGenOp"); addBootStrapOp("MilestoneWriteOp"); addMainLoopOp("SelectTournamentOp"); addMainLoopOp("GA-CrossoverOnePointBitStrOp"); addMainLoopOp("GA-MutationFlipBitStrOp"); addMainLoopOp(inEvalOp->getName()); addMainLoopOp("MigrationRandomRingOp"); addMainLoopOp("StatsCalcFitnessSimpleOp"); addMainLoopOp("TermMaxGenOp"); addMainLoopOp("MilestoneWriteOp"); }
//-------------------------------------------------------------------------------------------------- /// Add a quad strip /// /// Vertex ordering for quad strips: /// <PRE> /// v0 v2 v4 v6 Resulting quads: /// *-----*-----*-----* q1: v0, v1, v3, v2 /// | | | | q2: v2, v3, v5, v4 /// | | | | q3: v4, v5, v7, v6 /// | | | | /// *-----*-----*-----* /// v1 v3 v5 v7 </PRE> /// /// \remarks There must be at least 4 entries in the \a indices array, and the total number of /// entries must be a multiple of 2. //-------------------------------------------------------------------------------------------------- void GeometryBuilder::addQuadStrip(const UIntArray& indices) { size_t numIndices = indices.size(); CVF_ASSERT(numIndices >= 4); CVF_ASSERT(numIndices % 2 == 0); size_t numQuads = (numIndices - 2)/2; CVF_ASSERT(numQuads >= 1); size_t i; for (i = 0; i < numQuads; i++) { addQuad(indices[2*i], indices[2*i + 1], indices[2*i + 3], indices[2*i + 2]); } }
//-------------------------------------------------------------------------------------------------- /// Add multiple triangles /// /// \remarks There must be at least 3 entries in the \a indices array, and the total number of /// entries must be a multiple of 3. //-------------------------------------------------------------------------------------------------- void GeometryBuilder::addTriangles(const UIntArray& indices) { size_t numIndices = indices.size(); CVF_ASSERT(numIndices >= 3); CVF_ASSERT(numIndices % 3 == 0); size_t numTriangles = numIndices/3; CVF_ASSERT(numTriangles >= 1); CVF_ASSERT(3*numTriangles == numIndices); size_t i; for (i = 0; i < numTriangles; i++) { addTriangle(indices[3*i], indices[3*i + 1], indices[3*i + 2]); } }
//-------------------------------------------------------------------------------------------------- /// Add multiple quads /// /// The default implementation utilizes addQuad() to add each quad separately. /// /// \remarks There must be at least 4 entries in the \a indices array, and the total number of /// entries must be a multiple of 4. //-------------------------------------------------------------------------------------------------- void GeometryBuilder::addQuads(const UIntArray& indices) { size_t numIndices = indices.size(); CVF_ASSERT(numIndices >= 4); CVF_ASSERT(numIndices % 4 == 0); size_t numQuads = numIndices/4; CVF_ASSERT(numQuads >= 1); CVF_ASSERT(4*numQuads == numIndices); size_t i; for (i = 0; i < numQuads; i++) { addQuad(indices[4*i], indices[4*i + 1], indices[4*i + 2], indices[4*i + 3]); } }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- 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(OutlineEdgeExtractorTest, ThreeQuads) { ref<Vec3fArray> va = new Vec3fArray; va->reserve(8); va->add(Vec3f(0, 0, 0)); va->add(Vec3f(1, 0, 0)); va->add(Vec3f(2, 0, 0)); va->add(Vec3f(3, 0, 0)); va->add(Vec3f(0, 1, 0)); va->add(Vec3f(1, 1, 0)); va->add(Vec3f(2, 1, 0)); va->add(Vec3f(3, 1, 0)); // 4------5------6------7 // | | | | // | | | | // 0------1------2------3 OutlineEdgeExtractor ee(0, *va); { const cvf::uint conn[8] = { 0, 1, 5, 4, 1, 2, 6, 5 }; ee.addPrimitives(4, conn, 8); } { const cvf::uint conn[4] = { 2, 3, 7, 6 }; ee.addPrimitives(4, conn, 4); } UIntArray li = *ee.lineIndices(); ASSERT_EQ(2*8, li.size()); EXPECT_TRUE( EdgeKey(0, 1) == EdgeKey(li[ 0], li[ 1]) ); EXPECT_TRUE( EdgeKey(0, 4) == 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, 7) == EdgeKey(li[ 8], li[ 9]) ); EXPECT_TRUE( EdgeKey(4, 5) == EdgeKey(li[10], li[11]) ); EXPECT_TRUE( EdgeKey(5, 6) == EdgeKey(li[12], li[13]) ); EXPECT_TRUE( EdgeKey(6, 7) == EdgeKey(li[14], li[15]) ); }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- TEST(MeshEdgeExtractorTest, PrimitiveMixFromRawArrays) { // 6----5 // / \ *11 // / \ *12 // 8------7 4-----9 // | |\ / | // | | \ / | // 0------1--2----3 10 const cvf::uint points[2] = { 11, 12 }; const cvf::uint lines[4] = { 4, 9, 10, 9 }; const cvf::uint tri[3] = { 1, 2, 7 }; const cvf::uint quad[4] = { 0, 1, 7, 8 }; const cvf::uint poly[6] = { 2, 3, 4, 5, 6, 7 }; MeshEdgeExtractor ee; ee.addPrimitives(1, points, 2); ee.addPrimitives(2, lines, 4); ee.addPrimitives(3, tri, 3); ee.addPrimitives(4, quad, 4); ee.addPrimitives(6, poly, 6); 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]); }
//-------------------------------------------------------------------------------------------------- /// 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, CollapsedQuads) { // 4------3 6,6 // | |\ | // | | \ | // 0------1--2,2 5,5 const cvf::uint quads[12] = { 0, 1, 3, 4, 1, 2, 2, 3, 6, 5, 5, 6 }; MeshEdgeExtractor ee; ee.addPrimitives(4, quads, 12); UIntArray li = *ee.lineIndices(); ASSERT_EQ(2*7, li.size()); EXPECT_EQ(0, li[ 0]); EXPECT_EQ(1, li[ 1]); EXPECT_EQ(0, li[ 2]); EXPECT_EQ(4, li[ 3]); EXPECT_EQ(1, li[ 4]); EXPECT_EQ(2, li[ 5]); EXPECT_EQ(1, li[ 6]); EXPECT_EQ(3, li[ 7]); EXPECT_EQ(2, li[ 8]); EXPECT_EQ(3, li[ 9]); EXPECT_EQ(3, li[10]); EXPECT_EQ(4, li[11]); EXPECT_EQ(5, li[12]); EXPECT_EQ(6, li[13]); }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- 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()); } }
//-------------------------------------------------------------------------------------------------- /// 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()); } }
//-------------------------------------------------------------------------------------------------- /// //-------------------------------------------------------------------------------------------------- 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]) ); */ }
//-------------------------------------------------------------------------------------------------- /// 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(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]); } }