#include "GL_TriangleSet.h" #include "X3D_TriangleSet.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 { TriangleSet::TriangleSet() : X3DComposedGeometryNode() { define(Recorder::getTypeName("TriangleSet", "Rendering")); } TriangleSet::~TriangleSet() { } void TriangleSet::setN3F_V3F_vertexArray(const std::vector &N3F_V3F_vertexArray) { _N3F_V3F_vertexArray = N3F_V3F_vertexArray; } void TriangleSet::setC4F_N3F_V3F_vertexArray(const std::vector &C4F_N3F_V3F_vertexArray) { _C4F_N3F_V3F_vertexArray = C4F_N3F_V3F_vertexArray; } void TriangleSet::setT2F_N3F_V3F_vertexArray(const std::vector &T2F_N3F_V3F_vertexArray) { _T2F_N3F_V3F_vertexArray = T2F_N3F_V3F_vertexArray; } void TriangleSet::setT2F_C4F_N3F_V3F_vertexArray(const std::vector &T2F_C4F_N3F_V3F_vertexArray) { _T2F_C4F_N3F_V3F_vertexArray = T2F_C4F_N3F_V3F_vertexArray; } void TriangleSet::update() { if (x3dReference == 0) return; X3D::TriangleSet *T = static_cast(x3dReference); //emptying arrays _N3F_V3F_vertexArray.clear(); _C4F_N3F_V3F_vertexArray.clear(); _T2F_N3F_V3F_vertexArray.clear(); _T2F_C4F_N3F_V3F_vertexArray.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 TriangleSet::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); glInterleavedArrays(GL_T2F_C4F_N3F_V3F, 0, &_T2F_C4F_N3F_V3F_vertexArray.front()); glDrawArrays(GL_TRIANGLES, 0, _T2F_C4F_N3F_V3F_vertexArray.size()); glDisable(GL_COLOR_MATERIAL); } if ((getColor()) && (!getTexCoord())) { glEnable(GL_COLOR_MATERIAL); glInterleavedArrays(GL_C4F_N3F_V3F, 0, &_C4F_N3F_V3F_vertexArray.front()); glDrawArrays(GL_TRIANGLES, 0, _C4F_N3F_V3F_vertexArray.size()); glDisable(GL_COLOR_MATERIAL); } if ((!getColor()) && (getTexCoord())) { glInterleavedArrays(GL_C4F_N3F_V3F, 0, &_C4F_N3F_V3F_vertexArray.front()); glDrawArrays(GL_TRIANGLES, 0, _C4F_N3F_V3F_vertexArray.size()); } if ((!getColor()) && (!getTexCoord())) { glInterleavedArrays(GL_N3F_V3F, 0, &_N3F_V3F_vertexArray.front()); glDrawArrays(GL_TRIANGLES, 0, _N3F_V3F_vertexArray.size()); } if (getSolid()) glDisable(GL_CULL_FACE); } void TriangleSet::computeNoColorNoTexCoord(const MFVec3f &vertexArray, const MFVec3f &normalArray) { X3D::TriangleSet *T = static_cast(x3dReference); SFBool normalPerVertex = T->getNormalPerVertex(); if (normalPerVertex) { MFVec3f::const_iterator itNormal = normalArray.begin(); //iterate the coords for (MFVec3f::const_iterator itCoord = vertexArray.begin(); itCoord != vertexArray.end(); ++ itCoord) { N3F_V3F element; element.normal = *itNormal; element.vertex = *itCoord; _N3F_V3F_vertexArray.push_back(element); ++itNormal; } } else //normalPerVertex is FALSE { MFVec3f::const_iterator itNormal = normalArray.begin(); //iterate the coords unsigned int vertexCount = 0; for (MFVec3f::const_iterator itCoord = vertexArray.begin(); itCoord != vertexArray.end(); ++ itCoord) { N3F_V3F element; element.normal = *itNormal; element.vertex = *itCoord; _N3F_V3F_vertexArray.push_back(element); if ((vertexCount + 1)%3 == 0) ++itNormal; } } } void TriangleSet::computeColorNoTexCoord(const MFVec3f &vertexArray, const MFVec3f &normalArray) { X3D::TriangleSet *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(); if ((normalPerVertex) && (colorPerVertex)) { MFColorRGBA::const_iterator itColor = colorRGBA.begin(); MFVec3f::const_iterator itNormal = normalArray.begin(); //iterate the coords for (MFVec3f::const_iterator itCoord = vertexArray.begin(); itCoord != vertexArray.end(); ++itCoord) { C4F_N3F_V3F element; element.color = *itColor; element.normal = *itNormal; element.vertex = *itCoord; _C4F_N3F_V3F_vertexArray.push_back(element); ++itColor; ++itNormal; } } else //normalPerVertex or colorPertex is FALSE { MFColorRGBA::const_iterator itColor = colorRGBA.begin(); MFVec3f::const_iterator itNormal = normalArray.begin(); //iterate the coords unsigned int vertexCount = 0; for (MFVec3f::const_iterator itCoord = vertexArray.begin(); itCoord != vertexArray.end(); ++ itCoord) { C4F_N3F_V3F element; element.color = *itColor; element.normal = *itNormal; element.vertex = *itCoord; _C4F_N3F_V3F_vertexArray.push_back(element); if ((colorPerVertex) || ((vertexCount)%3 == 2)) ++itColor; if ((normalPerVertex) || ((vertexCount)%3 == 2)) ++itNormal; vertexCount++; } } } void TriangleSet::computeNoColorTexCoord(const MFVec3f &vertexArray, const MFVec3f &normalArray) { X3D::TriangleSet *T = static_cast(x3dReference); X3D::TextureCoordinate *TexCoordNode = dynamic_cast(T->getTexCoord()); if (TexCoordNode == 0) return; const MFVec2f &texCoordArray = TexCoordNode->getPoint(); SFBool normalPerVertex = T->getNormalPerVertex(); if (normalPerVertex) { MFVec2f::const_iterator itTexCoord = texCoordArray.begin(); MFVec3f::const_iterator itNormal = normalArray.begin(); //iterate the coords for (MFVec3f::const_iterator itCoord = vertexArray.begin(); itCoord != vertexArray.end(); ++itCoord) { T2F_N3F_V3F element; element.texCoord = *itTexCoord; element.normal = *itNormal; element.vertex = *itCoord; _T2F_N3F_V3F_vertexArray.push_back(element); ++itTexCoord; ++itNormal; } } else //normalPerVertex or colorPertex is FALSE { MFVec2f::const_iterator itTexCoord = texCoordArray.begin(); MFVec3f::const_iterator itNormal = normalArray.begin(); //iterate the coords unsigned int vertexCount = 0; for (MFVec3f::const_iterator itCoord = vertexArray.begin(); itCoord != vertexArray.end(); ++ itCoord) { T2F_N3F_V3F element; element.texCoord = *itTexCoord; element.normal = *itNormal; element.vertex = *itCoord; _T2F_N3F_V3F_vertexArray.push_back(element); ++itTexCoord; if ((normalPerVertex) || ((vertexCount)%3 == 2)) ++itNormal; vertexCount++; } } } void TriangleSet::computeColorTexCoord(const MFVec3f &vertexArray, const MFVec3f &normalArray) { X3D::TriangleSet *T = static_cast(x3dReference); MFColorRGBA array; MFColorRGBA &colorRGBA = array; if (T->getColor()->getTypeName() == "ColorRGBA") colorRGBA = static_cast(T->getColor())->getColor(); else colorRGBA = static_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(); if ((normalPerVertex) && (colorPerVertex)) { MFVec2f::const_iterator itTexCoord = texCoordArray.begin(); MFVec3f::const_iterator itNormal = normalArray.begin(); MFColorRGBA::const_iterator itColor = colorRGBA.begin(); //iterate the coords for (MFVec3f::const_iterator itCoord = vertexArray.begin(); itCoord != vertexArray.end(); ++itCoord) { T2F_C4F_N3F_V3F element; element.color = *itColor; element.texCoord = *itTexCoord; element.normal = *itNormal; element.vertex = *itCoord; _T2F_C4F_N3F_V3F_vertexArray.push_back(element); ++itTexCoord; ++itNormal; ++itColor; } } else //normalPerVertex or colorPertex is FALSE { MFVec2f::const_iterator itTexCoord = texCoordArray.begin(); MFVec3f::const_iterator itNormal = normalArray.begin(); MFColorRGBA::const_iterator itColor = colorRGBA.begin(); //iterate the coords unsigned int vertexCount = 0; for (MFVec3f::const_iterator itCoord = vertexArray.begin(); itCoord != vertexArray.end(); ++ itCoord) { T2F_C4F_N3F_V3F element; element.color = *itColor; element.texCoord = *itTexCoord; element.normal = *itNormal; element.vertex = *itCoord; _T2F_C4F_N3F_V3F_vertexArray.push_back(element); ++itTexCoord; if ((colorPerVertex) || ((vertexCount)%3 == 2)) ++itColor; if ((normalPerVertex) || ((vertexCount)%3 == 2)) ++itNormal; vertexCount++; } } } void TriangleSet::computeArrays(const MFVec3f &vertexArray, MFVec3f &normalArray) { X3D::TriangleSet *T = static_cast(x3dReference); SFBool normalPerVertex = T->getNormalPerVertex(); //computing the array containing the normals of each face MFVec3f normalFaceArray; MFVec3f::const_iterator itCoord = vertexArray.begin(); while (itCoord != vertexArray.end()) { SFVec3f A = *itCoord; ++itCoord; SFVec3f B = *itCoord; ++itCoord; SFVec3f C = *itCoord; ++itCoord; SFVec3f AB = B - A; SFVec3f AC = C - A; SFVec3f N; if (getCcw()) N = crossprod(AB, AC); else N = crossprod(AC, AB); N.normalize(); normalFaceArray.push_back(N); } if (normalPerVertex) { normalArray = MFVec3f(vertexArray.size()); MFVec3f::iterator itNormal = normalArray.begin(); for (MFVec3f::const_iterator itFace = normalFaceArray.begin(); itFace != normalFaceArray.end(); ++itFace) { *itNormal = *itFace; ++itNormal; *itNormal = *itFace; ++itNormal; *itNormal = *itFace; ++itNormal; } } else { //copying the values of normalFaceArray for (MFVec3f::const_iterator itFace = normalFaceArray.begin(); itFace != normalFaceArray.end(); ++itFace) normalArray.push_back(*itFace); } } } }