/* * MeshBasedNode.cpp * * Copyright (C) 1999 Stephen F. White, 2004 J. "MUFTI" Scheurich * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program (see the file "COPYING" for details); if * not, write to the Free Software Foundation, Inc., 675 Mass Ave, * Cambridge, MA 02139, USA. */ #include "stdafx.h" #include "MeshBasedNode.h" #include "Scene.h" #include "FieldValue.h" #include "SFInt32.h" #include "Mesh.h" #include "MFFloat.h" #include "MFInt32.h" #include "MFVec2f.h" #include "MFVec3f.h" #include "SFNode.h" #include "SFBool.h" #include "SFVec3f.h" #include "Vec2f.h" #include "Vec3f.h" #include "RenderState.h" #include "DuneApp.h" #include "NodeCoordinate.h" #include "NodeNormal.h" #include "NodeTextureCoordinate.h" #include "NodeIndexedFaceSet.h" MeshBasedNode::MeshBasedNode(Scene *scene, Proto *proto) : Node(scene, proto) { _mesh = NULL; _meshDirty = true; } MeshBasedNode::~MeshBasedNode() { delete _mesh; } void MeshBasedNode::draw() { if (_meshDirty) { createMesh(); _meshDirty = false; } if (!_mesh) return; _mesh->sort(); _mesh->draw(); } Node * MeshBasedNode::toIndexedFaceSet(bool wantNormal) { if (_meshDirty) { createMesh(); _meshDirty = false; } NodeCoordinate *ncoord = (NodeCoordinate *)_scene->createNode("Coordinate"); ncoord->point(_mesh->getVertices()); NodeIndexedFaceSet *node = (NodeIndexedFaceSet *) _scene->createNode("IndexedFaceSet"); node->coord(new SFNode(ncoord)); if (wantNormal) { NodeNormal *nnormal = NULL; if (_mesh->getNormals()) { nnormal = (NodeNormal *)_scene->createNode("Normal"); nnormal->vector(_mesh->getNormals()); } if (nnormal) node->normal(new SFNode(nnormal)); node->creaseAngle(new SFFloat(0)); } else node->creaseAngle(new SFFloat(_mesh->creaseAngle())); node->coordIndex(_mesh->getCoordIndex()); node->solid(new SFBool(_mesh->solid())); node->ccw(new SFBool(_mesh->ccw())); node->convex(new SFBool(_mesh->convex())); NodeTextureCoordinate *ntexCoord = NULL; if (_mesh->getTexCoords()) { ntexCoord = (NodeTextureCoordinate *) _scene->createNode("TextureCoordinate"); ntexCoord->point(_mesh->getTexCoords()); } if (ntexCoord) { node->texCoord(new SFNode(ntexCoord)); node->texCoordIndex(_mesh->getTexCoordIndex()); } return node; } Vec3f MeshBasedNode::getMinBoundingBox(void) { if (_meshDirty) { createMesh(); _meshDirty = false; } Vec3f ret(0, 0, 0); if (_mesh->getVertices()) return _mesh->getVertices()->getMinBoundingBox(); return ret; } Vec3f MeshBasedNode::getMaxBoundingBox(void) { if (_meshDirty) { createMesh(); _meshDirty = false; } Vec3f ret(0, 0, 0); if (_mesh->getVertices()) return _mesh->getVertices()->getMaxBoundingBox(); return ret; } MFVec3f * MeshBasedNode::getVertices(void) { if (_meshDirty) { createMesh(); _meshDirty = false; } if (_mesh == NULL) return NULL; return _mesh->getVertices(); } MFVec2f * MeshBasedNode::getTextureCoordinates() { if (_meshDirty) { createMesh(); _meshDirty = false; } if (_mesh == NULL) return NULL; return _mesh->generateTextureCoordinates(); } MFInt32 * MeshBasedNode::getTexCoordIndex() { if (_meshDirty) { createMesh(); _meshDirty = false; } if (_mesh == NULL) return NULL; return _mesh->getCoordIndex(); } int MeshBasedNode::cleanDoubleVertices(int *coordIndex, Vec3f *vertices, Vec3f *normals, int length, bool ccw) { int i; if (length < 2) return length; int *newCoordIndex = new int[length]; int newIndex = 1; newCoordIndex[0] = coordIndex[0]; for (i = 1; i < length; i++) if (coordIndex[i-1] < 0) newCoordIndex[newIndex++] = coordIndex[i]; else if (coordIndex[i] < 0) newCoordIndex[newIndex++] = coordIndex[i]; else { if ((vertices[coordIndex[i-1]] - vertices[coordIndex[i]]).length() > EPSILON) newCoordIndex[newIndex++] = coordIndex[i]; else { // reaccount normal for remaining vertex i-1 int index1 = i-2; int index2 = i; int index3 = i+1; if ((index1 < 0) || (index3 > length) || (coordIndex[index1] < 0) || (coordIndex[index2] < 0) || (coordIndex[index3] < 0)) { index1 = i-3; index2 = i-2; index3 = i; } if ((index1 < 0) || (index3 > length) || (coordIndex[index1] < 0) || (coordIndex[index2] < 0) || (coordIndex[index3] < 0)) { index1 = i; index2 = i+1; index3 = i+2; } if ((index1 < 0) || (index3 > length) || (coordIndex[index1] < 0) || (coordIndex[index2] < 0) || (coordIndex[index3] < 0)) { continue; } if (normals != NULL) { Vec3f edge = (vertices[coordIndex[index2]] - vertices[coordIndex[index1]]); normals[coordIndex[i]] = edge.cross( vertices[coordIndex[index3]] - vertices[coordIndex[index2]]); if (!ccw) normals[coordIndex[i]] = -normals[coordIndex[i]]; normals[coordIndex[i]].normalize(); normals[coordIndex[i-1]] = normals[coordIndex[i]]; } } } for (i = 0; i < newIndex; i++) coordIndex[i] = newCoordIndex[i]; delete [] newCoordIndex; return newIndex; } int MeshBasedNode::countPolygons(void) { int ret = 0; if (_meshDirty) { createMesh(); _meshDirty = false; } MFInt32 *coordIndex = _mesh->getCoordIndex(); if (coordIndex != NULL) { int lastCoordIndex = -1; for (int i = 0; i < coordIndex->getSize(); i++) { if ((coordIndex->getValue(i) == -1) && (lastCoordIndex != -1)) ret++; lastCoordIndex = coordIndex->getValue(i); } // need to count last polygon ? if (coordIndex->getSize() > 2) if (coordIndex->getValue(coordIndex->getSize() - 1) != -1) ret++; } return ret; }