#include "GL_TriangleStripSet.h" #include "X3D_TriangleStripSet.h" #include "X3D_Coordinate.h" #include "X3D_Color.h" #include "X3D_ColorRGBA.h" #include "X3D_Normal.h" #include "X3D_TextureCoordinate.h" #include using namespace std; namespace X3DTK { namespace GL { TriangleStripSet::TriangleStripSet() : X3DComposedGeometryNode() { define(Recorder::getTypeName("TriangleStripSet", "Rendering")); } TriangleStripSet::~TriangleStripSet() { } void TriangleStripSet::setN3F_V3F_vertexArrayArray(const std::vector > &N3F_V3F_vertexArrayArray) { _N3F_V3F_vertexArrayArray = N3F_V3F_vertexArrayArray; } void TriangleStripSet::setT2F_N3F_V3F_vertexArrayArray(const std::vector > &T2F_N3F_V3F_vertexArrayArray) { _T2F_N3F_V3F_vertexArrayArray = T2F_N3F_V3F_vertexArrayArray; } void TriangleStripSet::setC4F_N3F_V3F_vertexArrayArray(const std::vector > &C4F_N3F_V3F_vertexArrayArray) { _C4F_N3F_V3F_vertexArrayArray = C4F_N3F_V3F_vertexArrayArray; } void TriangleStripSet::setT2F_C4F_N3F_V3F_vertexArrayArray(const std::vector > &T2F_C4F_N3F_V3F_vertexArrayArray) { _T2F_C4F_N3F_V3F_vertexArrayArray = T2F_C4F_N3F_V3F_vertexArrayArray; } void TriangleStripSet::setVerticesDuplicated(bool value) { _verticesDuplicated = value; } void TriangleStripSet::update() { if (x3dReference == 0) return; X3D::TriangleStripSet *T = static_cast(x3dReference); _N3F_V3F_vertexArrayArray.clear(); _C4F_N3F_V3F_vertexArrayArray.clear(); _T2F_N3F_V3F_vertexArrayArray.clear(); _T2F_C4F_N3F_V3F_vertexArrayArray.clear(); X3D::Coordinate *CoordNode = dynamic_cast(T->getCoord()); if (CoordNode == 0) return; const MFVec3f &vertexArray = CoordNode->getPoint(); setSolid(T->getSolid()); setCcw(T->getCcw()); MFVec3f array; MFVec3f &normalArray = array; X3D::Normal *NormalNode = dynamic_cast(T->getNormal()); if (NormalNode != 0) normalArray = NormalNode->getVector(); else computeArrays(vertexArray, normalArray); if ((T->getColor() != 0) && (T->getTexCoord() != 0)) { setColor(true); setTexCoord(true); computeColorTexCoord(vertexArray, normalArray); } if ((T->getColor() != 0) && (T->getTexCoord() == 0)) { setColor(true); setTexCoord(false); computeColorNoTexCoord(vertexArray, normalArray); } if ((T->getColor() == 0) && (T->getTexCoord() != 0)) { setColor(false); setTexCoord(true); computeNoColorTexCoord(vertexArray, normalArray); } if ((T->getColor() == 0) && (T->getTexCoord() == 0)) { setColor(false); setTexCoord(false); computeNoColorNoTexCoord(vertexArray, normalArray); } } void TriangleStripSet::draw() const { if (getSolid()) { glEnable(GL_CULL_FACE); if (getCcw()) glFrontFace(GL_CCW); else glFrontFace(GL_CW); glCullFace(GL_BACK); } if ((getColor()) && (getTexCoord())) { } if ((getColor()) && (!getTexCoord())) { glEnable(GL_COLOR_MATERIAL); if (!getVerticesDuplicated()) { for (vector >::const_iterator itStripArray = _C4F_N3F_V3F_vertexArrayArray.begin(); itStripArray != _C4F_N3F_V3F_vertexArrayArray.end(); ++itStripArray) { glInterleavedArrays(GL_C4F_N3F_V3F, 0, &(*itStripArray).front()); glDrawArrays(GL_TRIANGLE_STRIP, 0, (*itStripArray).size()); } } else { for (vector >::const_iterator itStripArray = _C4F_N3F_V3F_vertexArrayArray.begin(); itStripArray != _C4F_N3F_V3F_vertexArrayArray.end(); ++itStripArray) { glInterleavedArrays(GL_C4F_N3F_V3F, 0, &(*itStripArray).front()); glDrawArrays(GL_TRIANGLES, 0, (*itStripArray).size()); } } glDisable(GL_COLOR_MATERIAL); } if ((!getColor()) && (getTexCoord())) { } if ((!getColor()) && (!getTexCoord())) { if (!getVerticesDuplicated()) { for (vector >::const_iterator itStripArray = _N3F_V3F_vertexArrayArray.begin(); itStripArray != _N3F_V3F_vertexArrayArray.end(); ++itStripArray) { glInterleavedArrays(GL_N3F_V3F, 0, &(*itStripArray).front()); glDrawArrays(GL_TRIANGLE_STRIP, 0, (*itStripArray).size()); } } else { for (vector >::const_iterator itStripArray = _N3F_V3F_vertexArrayArray.begin(); itStripArray != _N3F_V3F_vertexArrayArray.end(); ++itStripArray) { glInterleavedArrays(GL_N3F_V3F, 0, &(*itStripArray).front()); glDrawArrays(GL_TRIANGLES, 0, (*itStripArray).size()); } } } if (getSolid()) glDisable(GL_CULL_FACE); } void TriangleStripSet::computeNoColorNoTexCoord(const MFVec3f &vertexArray, const MFVec3f &normalArray) { X3D::TriangleStripSet *T = static_cast(x3dReference); SFBool normalPerVertex = T->getNormalPerVertex(); const MFInt32 &stripCount = T->getStripCount(); if (normalPerVertex) { setVerticesDuplicated(false); //using the GL_N3F_V3F if (normalPerVertex) { //using the GL_TRIANGLE_STRIP MFVec3f::const_iterator itCoord = vertexArray.begin(); MFVec3f::const_iterator itNormal = normalArray.begin(); //iterate the strips for (MFInt32::const_iterator itStrip = stripCount.begin(); itStrip != stripCount.end(); ++ itStrip) { //filling a new array _N3F_V3F_vertexArrayArray.push_back(vector()); for (SFInt32 i = 0; i < *itStrip; ++i) { N3F_V3F element; element.normal = *itNormal; element.vertex = *itCoord; _N3F_V3F_vertexArrayArray.back().push_back(element); ++itCoord; ++itNormal; } } } } else //normalPerVertex is FALSE { setVerticesDuplicated(true); //using the GL_TRIANGLES MFVec3f::const_iterator itCoord = vertexArray.begin(); MFVec3f::const_iterator itNormal = normalArray.begin(); //iterate the strips for (MFInt32::const_iterator itStrip = stripCount.begin(); itStrip != stripCount.end(); ++ itStrip) { //filling a new array _N3F_V3F_vertexArrayArray.push_back(vector()); N3F_V3F center; center.normal = *itNormal; center.vertex = *itCoord; ++itCoord; N3F_V3F element; element.normal = *itNormal; element.vertex = *itCoord; for (SFInt32 i = 2; i < *itStrip; ++i) { //push center center.normal = *itNormal; _N3F_V3F_vertexArrayArray.back().push_back(element); //push Pi element.normal = *itNormal; _N3F_V3F_vertexArrayArray.back().push_back(element); ++itCoord; //push Pi+1 element.normal = *itNormal; element.vertex = *itCoord; _N3F_V3F_vertexArrayArray.back().push_back(element); ++itNormal; } } } } void TriangleStripSet::computeColorNoTexCoord(const MFVec3f &vertexArray, const MFVec3f &normalArray) { X3D::TriangleStripSet *T = static_cast(x3dReference); MFColorRGBA array; MFColorRGBA &colorRGBA = array; if (T->getColor()->getTypeName() == "ColorRGBA") colorRGBA = dynamic_cast(T->getColor())->getColor(); else colorRGBA = dynamic_cast(T->getColor())->getColor(); SFBool normalPerVertex = T->getNormalPerVertex(); SFBool colorPerVertex = T->getColorPerVertex(); const MFInt32 &stripCount = T->getStripCount(); if ((normalPerVertex) && (colorPerVertex)) { setVerticesDuplicated(false); //using the GL_TRIANGLE_STRIP MFColorRGBA::const_iterator itColor = colorRGBA.begin(); MFVec3f::const_iterator itCoord = vertexArray.begin(); MFVec3f::const_iterator itNormal = normalArray.begin(); //iterate the strips for (MFInt32::const_iterator itStrip = stripCount.begin(); itStrip != stripCount.end(); ++ itStrip) { //filling a new array _C4F_N3F_V3F_vertexArrayArray.push_back(vector()); for (SFInt32 i = 0; i < *itStrip; ++i) { C4F_N3F_V3F element; element.color = *itColor; element.normal = *itNormal; element.vertex = *itCoord; _C4F_N3F_V3F_vertexArrayArray.back().push_back(element); ++itColor; ++itCoord; ++itNormal; } } } else //normalPerVertex or colorPertex is FALSE { setVerticesDuplicated(true); //using the GL_TRIANGLES MFColorRGBA::const_iterator itColor = colorRGBA.begin(); MFVec3f::const_iterator itCoord = vertexArray.begin(); MFVec3f::const_iterator itNormal = normalArray.begin(); //iterate the strips bool orientation = true; //var used to change the order of the vertices in the //case of culling for (MFInt32::const_iterator itStrip = stripCount.begin(); itStrip != stripCount.end(); ++ itStrip) { //filling a new array _C4F_N3F_V3F_vertexArrayArray.push_back(vector()); C4F_N3F_V3F P0; P0.color = *itColor; P0.normal = *itNormal; P0.vertex = *itCoord; ++itCoord; if (colorPerVertex) ++itColor; if (normalPerVertex) ++itNormal; C4F_N3F_V3F P1, P2; P1.color = *itColor; P1.normal = *itNormal; P1.vertex = *itCoord; for (SFInt32 i = 2; i < *itStrip; ++i) { //push center if (!colorPerVertex) P0.color = *itColor; if (!normalPerVertex) P0.normal = *itNormal; _C4F_N3F_V3F_vertexArrayArray.back().push_back(P0); //push Pi if (!colorPerVertex) P1.color = *itColor; if (!normalPerVertex) P1.normal = *itNormal; ++itCoord; if (colorPerVertex) ++itColor; if (normalPerVertex) ++itNormal; //push Pi+1 P2.color = *itColor; P2.normal = *itNormal; P2.vertex = *itCoord; if (orientation) { _C4F_N3F_V3F_vertexArrayArray.back().push_back(P1); _C4F_N3F_V3F_vertexArrayArray.back().push_back(P2); } else { _C4F_N3F_V3F_vertexArrayArray.back().push_back(P2); _C4F_N3F_V3F_vertexArrayArray.back().push_back(P1); } orientation = !orientation; if (!colorPerVertex) ++itColor; if (!normalPerVertex) ++itNormal; //P0 becomes P1, P1 P2 P0 = P1; P1 = P2; } } } } void TriangleStripSet::computeNoColorTexCoord(const MFVec3f &vertexArray, const MFVec3f &normalArray) { X3D::TriangleStripSet *T = static_cast(x3dReference); X3D::TextureCoordinate *TexCoordNode = dynamic_cast(T->getTexCoord()); if (TexCoordNode == 0) return; const MFVec2f &texCoordArray = TexCoordNode->getPoint(); SFBool normalPerVertex = T->getNormalPerVertex(); const MFInt32 &stripCount = T->getStripCount(); if (normalPerVertex) { setVerticesDuplicated(false); //using the GL_TRIANGLE_STRIP MFVec2f::const_iterator itTexCoord = texCoordArray.begin(); MFVec3f::const_iterator itCoord = vertexArray.begin(); MFVec3f::const_iterator itNormal = normalArray.begin(); //iterate the strips for (MFInt32::const_iterator itStrip = stripCount.begin(); itStrip != stripCount.end(); ++ itStrip) { //filling a new array _T2F_N3F_V3F_vertexArrayArray.push_back(vector()); for (SFInt32 i = 0; i < *itStrip; ++i) { T2F_N3F_V3F element; element.texCoord = *itTexCoord; element.normal = *itNormal; element.vertex = *itCoord; _T2F_N3F_V3F_vertexArrayArray.back().push_back(element); ++itTexCoord; ++itCoord; ++itNormal; } } } else //normalPerVertex or colorPertex is FALSE { setVerticesDuplicated(true); //using the GL_TRIANGLES MFVec2f::const_iterator itTexCoord = texCoordArray.begin(); MFVec3f::const_iterator itCoord = vertexArray.begin(); MFVec3f::const_iterator itNormal = normalArray.begin(); //iterate the strips bool orientation = true; //var used to change the order of the vertices in the //case of culling for (MFInt32::const_iterator itStrip = stripCount.begin(); itStrip != stripCount.end(); ++ itStrip) { //filling a new array _T2F_N3F_V3F_vertexArrayArray.push_back(vector()); T2F_N3F_V3F P0; P0.texCoord = *itTexCoord; P0.normal = *itNormal; P0.vertex = *itCoord; ++itCoord; ++itTexCoord; if (normalPerVertex) ++itNormal; T2F_N3F_V3F P1, P2; P1.texCoord = *itTexCoord; P1.normal = *itNormal; P1.vertex = *itCoord; for (SFInt32 i = 2; i < *itStrip; ++i) { //push center if (!normalPerVertex) P0.normal = *itNormal; _T2F_N3F_V3F_vertexArrayArray.back().push_back(P0); //push Pi if (!normalPerVertex) P1.normal = *itNormal; ++itCoord; ++itTexCoord; if (normalPerVertex) ++itNormal; //push Pi+1 P2.texCoord = *itTexCoord; P2.normal = *itNormal; P2.vertex = *itCoord; if (orientation) { _T2F_N3F_V3F_vertexArrayArray.back().push_back(P1); _T2F_N3F_V3F_vertexArrayArray.back().push_back(P2); } else { _T2F_N3F_V3F_vertexArrayArray.back().push_back(P2); _T2F_N3F_V3F_vertexArrayArray.back().push_back(P1); } orientation = !orientation; if (!normalPerVertex) ++itNormal; //P0 becomes P1, P1 P2 P0 = P1; P1 = P2; } } } } void TriangleStripSet::computeColorTexCoord(const MFVec3f &vertexArray, const MFVec3f &normalArray) { X3D::TriangleStripSet *T = static_cast(x3dReference); MFColorRGBA array; MFColorRGBA &colorRGBA = array; if (T->getColor()->getTypeName() == "ColorRGBA") colorRGBA = dynamic_cast(T->getColor())->getColor(); else colorRGBA = dynamic_cast(T->getColor())->getColor(); X3D::TextureCoordinate *TexCoordNode = dynamic_cast(T->getTexCoord()); if (TexCoordNode == 0) return; const MFVec2f &texCoordArray = TexCoordNode->getPoint(); SFBool normalPerVertex = T->getNormalPerVertex(); SFBool colorPerVertex = T->getColorPerVertex(); const MFInt32 &stripCount = T->getStripCount(); if ((normalPerVertex) && (colorPerVertex)) { setVerticesDuplicated(false); //using the GL_TRIANGLE_STRIP MFColorRGBA::const_iterator itColor = colorRGBA.begin(); MFVec2f::const_iterator itTexCoord = texCoordArray.begin(); MFVec3f::const_iterator itCoord = vertexArray.begin(); MFVec3f::const_iterator itNormal = normalArray.begin(); //iterate the strips for (MFInt32::const_iterator itStrip = stripCount.begin(); itStrip != stripCount.end(); ++ itStrip) { //filling a new array _T2F_C4F_N3F_V3F_vertexArrayArray.push_back(vector()); for (SFInt32 i = 0; i < *itStrip; ++i) { T2F_C4F_N3F_V3F element; element.color = *itColor; element.normal = *itNormal; element.vertex = *itCoord; _T2F_C4F_N3F_V3F_vertexArrayArray.back().push_back(element); ++itColor; ++itTexCoord; ++itCoord; ++itNormal; } } } else //normalPerVertex or colorPertex is FALSE { setVerticesDuplicated(true); //using the GL_TRIANGLES MFColorRGBA::const_iterator itColor = colorRGBA.begin(); MFVec2f::const_iterator itTexCoord = texCoordArray.begin(); MFVec3f::const_iterator itCoord = vertexArray.begin(); MFVec3f::const_iterator itNormal = normalArray.begin(); //iterate the strips bool orientation = true; //var used to change the order of the vertices in the //case of culling for (MFInt32::const_iterator itStrip = stripCount.begin(); itStrip != stripCount.end(); ++ itStrip) { //filling a new array _T2F_C4F_N3F_V3F_vertexArrayArray.push_back(vector()); T2F_C4F_N3F_V3F P0; P0.color = *itColor; P0.texCoord = *itTexCoord; P0.normal = *itNormal; P0.vertex = *itCoord; ++itCoord; ++itTexCoord; if (colorPerVertex) ++itColor; if (normalPerVertex) ++itNormal; T2F_C4F_N3F_V3F P1, P2; P1.color = *itColor; P1.texCoord = *itTexCoord; P1.normal = *itNormal; P1.vertex = *itCoord; for (SFInt32 i = 2; i < *itStrip; ++i) { //push center if (!colorPerVertex) P0.color = *itColor; if (!normalPerVertex) P0.normal = *itNormal; _T2F_C4F_N3F_V3F_vertexArrayArray.back().push_back(P0); //push Pi if (!colorPerVertex) P1.color = *itColor; if (!normalPerVertex) P1.normal = *itNormal; ++itCoord; ++itTexCoord; if (colorPerVertex) ++itColor; if (normalPerVertex) ++itNormal; //push Pi+1 P2.color = *itColor; P2.texCoord = *itTexCoord; P2.normal = *itNormal; P2.vertex = *itCoord; if (orientation) { _T2F_C4F_N3F_V3F_vertexArrayArray.back().push_back(P1); _T2F_C4F_N3F_V3F_vertexArrayArray.back().push_back(P2); } else { _T2F_C4F_N3F_V3F_vertexArrayArray.back().push_back(P2); _T2F_C4F_N3F_V3F_vertexArrayArray.back().push_back(P1); } orientation = !orientation; if (!colorPerVertex) ++itColor; if (!normalPerVertex) ++itNormal; //P0 becomes P1, P1 P2 P0 = P1; P1 = P2; } } } } void TriangleStripSet::computeArrays(const MFVec3f &vertexArray, MFVec3f &normalArray) { X3D::TriangleStripSet *T = static_cast(x3dReference); SFBool normalPerVertex = T->getNormalPerVertex(); const MFInt32 &stripCount = T->getStripCount(); //computing the array containing the normals of each face MFVec3f normalFaceArray; bool orientation = true; MFVec3f::const_iterator itCoord = vertexArray.begin(); for (MFInt32::const_iterator itStrip = stripCount.begin(); itStrip != stripCount.end(); ++itStrip) { SFVec3f A = *itCoord; ++itCoord; SFVec3f B = *itCoord; ++itCoord; for (SFInt32 i = 2; i < *itStrip; ++i) { SFVec3f C = *itCoord; ++itCoord; //computing the normal following ccw SFVec3f AB = B - A; SFVec3f AC = C - A; SFVec3f N; if (getCcw()) { if (orientation) N = crossprod(AB, AC); else N = crossprod(AC, AB); } else { if (orientation) N = crossprod(AC, AB); else N = crossprod(AB, AC); } N.normalize(); normalFaceArray.push_back(N); A = B; B = C; orientation = !orientation; } } if (normalPerVertex) { normalArray = MFVec3f(vertexArray.size()); //iterate the fans MFVec3f::iterator itNormal = normalArray.begin(); MFVec3f::const_iterator itFace = normalFaceArray.begin(); for (MFInt32::const_iterator itStrip = stripCount.begin(); itStrip != stripCount.end(); ++itStrip) { SFVec3f N0, N1, N2; N0 = *itFace; ++itFace; *itNormal = N0; ++itNormal; N1 = *itFace; ++itFace; *itNormal = N0 + N1; (*itNormal).normalize(); ++itNormal; for (SFInt32 i = 0; i < *itStrip - 4; ++i) { N2 = *itFace; ++itFace; *itNormal = N0 + N1 + N2; (*itNormal).normalize(); N0 = N1; N1 = N2; ++itNormal; } *itNormal = N1 + N2; (*itNormal).normalize(); ++itNormal; *itNormal = N2; } } else { //copying the values of normalFaceArray for (MFVec3f::const_iterator itFace = normalFaceArray.begin(); itFace != normalFaceArray.end(); ++itFace) normalArray.push_back(*itFace); } } } }