#include "GL_TriangleFanSet.h" #include "X3D_TriangleFanSet.h" #include "X3D_Coordinate.h" #include "X3D_TextureCoordinate.h" #include "X3D_Color.h" #include "X3D_ColorRGBA.h" #include "X3D_Normal.h" #include using namespace std; namespace X3DTK { namespace GL { TriangleFanSet::TriangleFanSet() : X3DComposedGeometryNode() { define(Recorder::getTypeName("TriangleFanSet", "Rendering")); } TriangleFanSet::~TriangleFanSet() { } void TriangleFanSet::setC4F_N3F_V3F_vertexArrayArray(const std::vector > &C4F_N3F_V3F_vertexArrayArray) { _C4F_N3F_V3F_vertexArrayArray = C4F_N3F_V3F_vertexArrayArray; } void TriangleFanSet::setN3F_V3F_vertexArrayArray(const std::vector > &N3F_V3F_vertexArrayArray) { _N3F_V3F_vertexArrayArray = N3F_V3F_vertexArrayArray; } void TriangleFanSet::setT2F_C4F_N3F_V3F_vertexArrayArray(const std::vector > &T2F_C4F_N3F_V3F_vertexArrayArray) { _T2F_C4F_N3F_V3F_vertexArrayArray = T2F_C4F_N3F_V3F_vertexArrayArray; } void TriangleFanSet::setT2F_N3F_V3F_vertexArrayArray(const std::vector > &T2F_N3F_V3F_vertexArrayArray) { _T2F_N3F_V3F_vertexArrayArray = T2F_N3F_V3F_vertexArrayArray; } void TriangleFanSet::setVerticesDuplicated(bool value) { _verticesDuplicated = value; } void TriangleFanSet::update() { if (x3dReference == 0) return; X3D::TriangleFanSet *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 TriangleFanSet::draw() const { if (getSolid()) { glEnable(GL_CULL_FACE); if (getCcw()) glFrontFace(GL_CCW); else glFrontFace(GL_CW); glCullFace(GL_BACK); } if ((getColor()) && (getTexCoord())) { glEnable(GL_COLOR_MATERIAL); if (!getVerticesDuplicated()) { for (vector >::const_iterator itFanArray = _T2F_C4F_N3F_V3F_vertexArrayArray.begin(); itFanArray != _T2F_C4F_N3F_V3F_vertexArrayArray.end(); ++itFanArray) { glInterleavedArrays(GL_T2F_C4F_N3F_V3F, 0, &(*itFanArray).front()); glDrawArrays(GL_TRIANGLE_FAN, 0, (*itFanArray).size()); } } else { for (vector >::const_iterator itFanArray = _T2F_C4F_N3F_V3F_vertexArrayArray.begin(); itFanArray != _T2F_C4F_N3F_V3F_vertexArrayArray.end(); ++itFanArray) { glInterleavedArrays(GL_T2F_C4F_N3F_V3F, 0, &(*itFanArray).front()); glDrawArrays(GL_TRIANGLES, 0, (*itFanArray).size()); } } glDisable(GL_COLOR_MATERIAL); } if ((getColor()) && (!getTexCoord())) { glEnable(GL_COLOR_MATERIAL); if (!getVerticesDuplicated()) { for (vector >::const_iterator itFanArray = _C4F_N3F_V3F_vertexArrayArray.begin(); itFanArray != _C4F_N3F_V3F_vertexArrayArray.end(); ++itFanArray) { glInterleavedArrays(GL_C4F_N3F_V3F, 0, &(*itFanArray).front()); glDrawArrays(GL_TRIANGLE_FAN, 0, (*itFanArray).size()); } } else { for (vector >::const_iterator itFanArray = _C4F_N3F_V3F_vertexArrayArray.begin(); itFanArray != _C4F_N3F_V3F_vertexArrayArray.end(); ++itFanArray) { glInterleavedArrays(GL_C4F_N3F_V3F, 0, &(*itFanArray).front()); glDrawArrays(GL_TRIANGLES, 0, (*itFanArray).size()); } } glDisable(GL_COLOR_MATERIAL); } if ((!getColor()) && (getTexCoord())) { if (!getVerticesDuplicated()) { for (vector >::const_iterator itFanArray = _T2F_N3F_V3F_vertexArrayArray.begin(); itFanArray != _T2F_N3F_V3F_vertexArrayArray.end(); ++itFanArray) { glInterleavedArrays(GL_T2F_N3F_V3F, 0, &(*itFanArray).front()); glDrawArrays(GL_TRIANGLE_FAN, 0, (*itFanArray).size()); } } else { for (vector >::const_iterator itFanArray = _T2F_N3F_V3F_vertexArrayArray.begin(); itFanArray != _T2F_N3F_V3F_vertexArrayArray.end(); ++itFanArray) { glInterleavedArrays(GL_T2F_N3F_V3F, 0, &(*itFanArray).front()); glDrawArrays(GL_TRIANGLES, 0, (*itFanArray).size()); } } } if ((!getColor()) && (!getTexCoord())) { if (!getVerticesDuplicated()) { for (vector >::const_iterator itFanArray = _N3F_V3F_vertexArrayArray.begin(); itFanArray != _N3F_V3F_vertexArrayArray.end(); ++itFanArray) { glInterleavedArrays(GL_N3F_V3F, 0, &(*itFanArray).front()); glDrawArrays(GL_TRIANGLE_FAN, 0, (*itFanArray).size()); } } else { for (vector >::const_iterator itFanArray = _N3F_V3F_vertexArrayArray.begin(); itFanArray != _N3F_V3F_vertexArrayArray.end(); ++itFanArray) { glInterleavedArrays(GL_N3F_V3F, 0, &(*itFanArray).front()); glDrawArrays(GL_TRIANGLES, 0, (*itFanArray).size()); } } } if (getSolid()) glDisable(GL_CULL_FACE); } void TriangleFanSet::computeNoColorNoTexCoord(const MFVec3f &vertexArray, const MFVec3f &normalArray) { X3D::TriangleFanSet *T = static_cast(x3dReference); SFBool normalPerVertex = T->getNormalPerVertex(); const MFInt32 &fanCount = T->getFanCount(); if (normalPerVertex) { setVerticesDuplicated(false); //using the GL_TRIANGLE_FAN MFVec3f::const_iterator itCoord = vertexArray.begin(); MFVec3f::const_iterator itNormal = normalArray.begin(); //iterate the fans for (MFInt32::const_iterator itFan = fanCount.begin(); itFan != fanCount.end(); ++ itFan) { //filling a new array _N3F_V3F_vertexArrayArray.push_back(vector()); for (SFInt32 i = 0; i < *itFan; ++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 fans for (MFInt32::const_iterator itFan = fanCount.begin(); itFan != fanCount.end(); ++ itFan) { //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 < *itFan; ++i) { //push center center.normal = *itNormal; _N3F_V3F_vertexArrayArray.back().push_back(center); //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; } ++itCoord; ++itNormal; } } } void TriangleFanSet::computeColorNoTexCoord(const MFVec3f &vertexArray, const MFVec3f &normalArray) { X3D::TriangleFanSet *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 &fanCount = T->getFanCount(); if ((normalPerVertex) && (colorPerVertex)) { setVerticesDuplicated(false); //using the GL_TRIANGLE_FAN MFColorRGBA::const_iterator itColor = colorRGBA.begin(); MFVec3f::const_iterator itCoord = vertexArray.begin(); MFVec3f::const_iterator itNormal = normalArray.begin(); //iterate the fans for (MFInt32::const_iterator itFan = fanCount.begin(); itFan != fanCount.end(); ++ itFan) { //filling a new array _C4F_N3F_V3F_vertexArrayArray.push_back(vector()); for (SFInt32 i = 0; i < *itFan; ++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 fans for (MFInt32::const_iterator itFan = fanCount.begin(); itFan != fanCount.end(); ++ itFan) { //filling a new array _C4F_N3F_V3F_vertexArrayArray.push_back(vector()); C4F_N3F_V3F center; center.color = *itColor; center.normal = *itNormal; center.vertex = *itCoord; ++itCoord; if (colorPerVertex) ++itColor; if (normalPerVertex) ++itNormal; C4F_N3F_V3F element; element.color = *itColor; element.normal = *itNormal; element.vertex = *itCoord; for (SFInt32 i = 2; i < *itFan; ++i) { //push center if (!colorPerVertex) center.color = *itColor; if (!normalPerVertex) center.normal = *itNormal; _C4F_N3F_V3F_vertexArrayArray.back().push_back(center); //push Pi if (!colorPerVertex) element.color = *itColor; if (!normalPerVertex) element.normal = *itNormal; _C4F_N3F_V3F_vertexArrayArray.back().push_back(element); ++itCoord; if (colorPerVertex) ++itColor; if (normalPerVertex) ++itNormal; //push Pi+1 element.color = *itColor; element.normal = *itNormal; element.vertex = *itCoord; _C4F_N3F_V3F_vertexArrayArray.back().push_back(element); if (!colorPerVertex) ++itColor; if (!normalPerVertex) ++itNormal; } ++itCoord; ++itColor; ++itNormal; } } } void TriangleFanSet::computeNoColorTexCoord(const MFVec3f &vertexArray, const MFVec3f &normalArray) { X3D::TriangleFanSet *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 &fanCount = T->getFanCount(); if (normalPerVertex) { setVerticesDuplicated(false); //using the GL_TRIANGLE_FAN MFVec2f::const_iterator itTexCoord = texCoordArray.begin(); MFVec3f::const_iterator itCoord = vertexArray.begin(); MFVec3f::const_iterator itNormal = normalArray.begin(); //iterate the fans for (MFInt32::const_iterator itFan = fanCount.begin(); itFan != fanCount.end(); ++ itFan) { //filling a new array _T2F_N3F_V3F_vertexArrayArray.push_back(vector()); for (SFInt32 i = 0; i < *itFan; ++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 fans for (MFInt32::const_iterator itFan = fanCount.begin(); itFan != fanCount.end(); ++ itFan) { //filling a new array _T2F_N3F_V3F_vertexArrayArray.push_back(vector()); T2F_N3F_V3F center; center.texCoord = *itTexCoord; center.normal = *itNormal; center.vertex = *itCoord; ++itCoord; ++itTexCoord; if (normalPerVertex) ++itNormal; T2F_N3F_V3F element; element.texCoord = *itTexCoord; element.normal = *itNormal; element.vertex = *itCoord; for (SFInt32 i = 2; i < *itFan; ++i) { //push center if (!normalPerVertex) center.normal = *itNormal; _T2F_N3F_V3F_vertexArrayArray.back().push_back(element); //push Pi if (!normalPerVertex) element.normal = *itNormal; _T2F_N3F_V3F_vertexArrayArray.back().push_back(element); ++itCoord; ++itTexCoord; if (normalPerVertex) ++itNormal; //push Pi+1 element.texCoord = *itTexCoord; element.normal = *itNormal; element.vertex = *itCoord; _T2F_N3F_V3F_vertexArrayArray.back().push_back(element); if (!normalPerVertex) ++itNormal; } ++itCoord; ++itTexCoord; ++itNormal; } } } void TriangleFanSet::computeColorTexCoord(const MFVec3f &vertexArray, const MFVec3f &normalArray) { X3D::TriangleFanSet *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 &fanCount = T->getFanCount(); if ((normalPerVertex) && (colorPerVertex)) { setVerticesDuplicated(false); //using the GL_TRIANGLE_FAN 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 fans for (MFInt32::const_iterator itFan = fanCount.begin(); itFan != fanCount.end(); ++ itFan) { //filling a new array _T2F_C4F_N3F_V3F_vertexArrayArray.push_back(vector()); for (SFInt32 i = 0; i < *itFan; ++i) { T2F_C4F_N3F_V3F element; element.texCoord = *itTexCoord; element.color = *itColor; element.normal = *itNormal; element.vertex = *itCoord; _T2F_C4F_N3F_V3F_vertexArrayArray.back().push_back(element); ++itTexCoord; ++itColor; ++itCoord; ++itNormal; } } } else //normalPerVertex or colorPertex is FALSE { setVerticesDuplicated(true); //using the GL_TRIANGLES MFVec2f::const_iterator itTexCoord = texCoordArray.begin(); MFColorRGBA::const_iterator itColor = colorRGBA.begin(); MFVec3f::const_iterator itCoord = vertexArray.begin(); MFVec3f::const_iterator itNormal = normalArray.begin(); //iterate the fans for (MFInt32::const_iterator itFan = fanCount.begin(); itFan != fanCount.end(); ++ itFan) { //filling a new array _T2F_C4F_N3F_V3F_vertexArrayArray.push_back(vector()); T2F_C4F_N3F_V3F center; center.texCoord = *itTexCoord; center.color = *itColor; center.normal = *itNormal; center.vertex = *itCoord; ++itCoord; ++itTexCoord; if (colorPerVertex) ++itColor; if (normalPerVertex) ++itNormal; T2F_C4F_N3F_V3F element; element.texCoord = *itTexCoord; element.color = *itColor; element.normal = *itNormal; element.vertex = *itCoord; for (SFInt32 i = 2; i < *itFan; ++i) { //push center if (!colorPerVertex) center.color = *itColor; if (!normalPerVertex) center.normal = *itNormal; _T2F_C4F_N3F_V3F_vertexArrayArray.back().push_back(element); //push Pi if (!colorPerVertex) element.color = *itColor; if (!normalPerVertex) element.normal = *itNormal; _T2F_C4F_N3F_V3F_vertexArrayArray.back().push_back(element); ++itCoord; ++itTexCoord; if (colorPerVertex) ++itColor; if (normalPerVertex) ++itNormal; //push Pi+1 element.texCoord = *itTexCoord; element.color = *itColor; element.normal = *itNormal; element.vertex = *itCoord; _T2F_C4F_N3F_V3F_vertexArrayArray.back().push_back(element); if (!colorPerVertex) ++itColor; if (!normalPerVertex) ++itNormal; } ++itCoord; ++itTexCoord; ++itColor; ++itNormal; } } } void TriangleFanSet::computeArrays(const MFVec3f &vertexArray, MFVec3f &normalArray) { X3D::TriangleFanSet *T = static_cast(x3dReference); SFBool normalPerVertex = T->getNormalPerVertex(); const MFInt32 &fanCount = T->getFanCount(); //computing the array containing the normals of each face MFVec3f normalFaceArray; MFVec3f::const_iterator itCoord = vertexArray.begin(); for (MFInt32::const_iterator itFan = fanCount.begin(); itFan != fanCount.end(); ++itFan) { SFVec3f Center = *itCoord; ++itCoord; SFVec3f A = *itCoord; ++itCoord; for (SFInt32 i = 2; i < *itFan; ++i) { SFVec3f B = *itCoord; ++itCoord; //computing the normal following _ccw SFVec3f AB = B - A; SFVec3f AC = Center - A; SFVec3f N; if (getCcw()) N = crossprod(AB, AC); else N = crossprod(AC, AB); N.normalize(); normalFaceArray.push_back(N); A = B; } } if (normalPerVertex) { normalArray = MFVec3f(vertexArray.size()); //iterate the fans MFVec3f::iterator itNormal = normalArray.begin(); MFVec3f::const_iterator itFace = normalFaceArray.begin(); for (MFInt32::const_iterator itFan = fanCount.begin(); itFan != fanCount.end(); ++itFan) { SFVec3f N0, N1; SFVec3f *Center = &(*itNormal); //memorizing the center of the fan ++itNormal;//positioning on the second point N0 = *itFace; *Center = *Center + N0; ++itFace; *itNormal = N0;//the first point has the normal of the first face ++itNormal; for (SFInt32 i = 0; i < *itFan - 3; ++i) { N1 = *itFace; *Center = *Center + N1; SFVec3f N = N0 + N1; N.normalize(); *itNormal = N; N0 = N1; ++itNormal; } *itNormal = N1; Center->normalize();//normalizing the center of the fan } } else { //copying the values of normalFaceArray for (MFVec3f::const_iterator itFace = normalFaceArray.begin(); itFace != normalFaceArray.end(); ++itFace) normalArray.push_back(*itFace); } } } }