/* * NodeBox.cpp * * Copyright (C) 1999 Stephen F. White * * 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 #include "stdafx.h" #include "NodeBox.h" #include "Scene.h" #include "Proto.h" #include "FieldValue.h" #include "FieldCommand.h" #include "SFVec3f.h" #include "SFFloat.h" #include "RenderState.h" #include "Node.h" #include "Util.h" #include "MFNode.h" #include "SFNode.h" #include "SFInt32.h" //#include "MFFloat.h" #include "MFVec3f.h" #include "NodeShape.h" #include "NodeAppearance.h" #include "NodeMaterial.h" #include "NodeNurbsGroup.h" #include "NodeNurbsSurface.h" #include "Util.h" ProtoBox::ProtoBox(Scene *scene) : Proto(scene, "Box") { size.set( addField(SFVEC3F, "size", new SFVec3f(2.0f, 2.0f, 2.0f), new SFFloat(0.0f))); } Node * ProtoBox::create(Scene *scene) { return new NodeBox(scene, this); } NodeBox::NodeBox(Scene *scene, Proto *def) : Node(scene, def) { } void NodeBox::draw() { const float *fsize = size()->getValue(); Util::DrawBox(fsize[0] * 0.5f, fsize[1] * 0.5f, fsize[2] * 0.5f); } void NodeBox::drawHandles() { const float *fsize = size()->getValue(); RenderState state; glPushMatrix(); glScalef(fsize[0] * 0.5f, fsize[1] * 0.5f, fsize[2] * 0.5f); glPushAttrib(GL_LIGHTING); glDisable(GL_LIGHTING); glPushName(0); Util::myGlColor3f(1.0f, 1.0f, 1.0f); state.startDrawHandles(); for (int i = 0; i < 8; i++) { glLoadName(i); state.drawHandle(boxCorners[i]); } state.endDrawHandles(); glPopName(); glPopAttrib(); glPopMatrix(); } Vec3f NodeBox::getHandle(int handle, int * /* constraint */, int *field) { const float *fsize = size()->getValue(); switch (handle) { case TRF: case TLF: case TRB: case TLB: case BRF: case BLF: case BRB: case BLB: *field = 0; return Vec3f(fsize) * Vec3f(boxCorners[handle]) * 0.5f; default: assert(0); return Vec3f(0.0f, 0.0f, 0.0f); } } void NodeBox::setHandle(int handle, const Vec3f &v) { switch (handle) { case TRF: case TLF: case TRB: case TLB: case BRF: case BLF: case BRB: case BLB: _scene->setField(this, size_Index(), new SFVec3f(v * 2.0f * Vec3f(boxCorners[handle]))); break; } } Node* NodeBox::toNurbs(int nuAreaPoints, int uDegree, int nvAreaPoints, int vDegree, int nzAreaPoints) { //build a box with NURBS from 1 surface const float *fsize = size()->getValue(); Node *node = _scene->createNode("NurbsSurface"); int i,j; int index1 = 0; int index2; int tmpindex; float xSize = fsize[0]; float ySize = fsize[1]; float zSize = fsize[2]; float dz = zSize / (nvAreaPoints - 1); float tmpxSize; float tmpySize; float zPosition; int uOrder = uDegree + 1; int vOrder = vDegree + 1; int uDimension = 4 * nuAreaPoints + 4 * uDegree - 7; int vDimension = nvAreaPoints + 2 * (nzAreaPoints-1) + 2*vDegree - 2; float *uKnots = new float[uDimension + uOrder]; float *vKnots = new float[vDimension + vOrder]; float *controlPoints = new float[uDimension * vDimension * 3]; float *weights = new float[uDimension * vDimension]; for(i=0; isetField(0, new SFInt32(uDimension)); node->setField(1, new SFInt32(vDimension)); node->setField(2, new MFFloat(uKnots, uDimension + uOrder)); node->setField(3, new MFFloat(vKnots, vDimension + vOrder)); node->setField(4, new SFInt32(uOrder)); node->setField(5, new SFInt32(vOrder)); node->setField(6, new MFVec3f(controlPoints, uDimension * vDimension * 3)); node->setField(7, new MFFloat(weights, uDimension * vDimension)); return node; } Node* NodeBox::toNurbs(int nuAreaPoints, int uDegree, int nvAreaPoints, int vDegree) { //build a box with NURBS from 6 seperate NURBS-surfaces Node *node = _scene->createNode("NurbsGroup"); FieldValue *box = new MFNode(); const float *fsize = size()->getValue(); _xSize = fsize[0]; _ySize = fsize[1]; _zSize = fsize[2]; _nuAreaPoints = nuAreaPoints; _nvAreaPoints = nvAreaPoints; _uOrder = uDegree + 1; _vOrder = vDegree + 1; _uDimension = nuAreaPoints; _vDimension = nvAreaPoints; int i; //NodeList for(i=1; i<7; i++){ Node *surface = _makeNurbsSurfaces(i); NodeShape *nShape = (NodeShape *) _scene->createNode("Shape"); NodeAppearance *nAppearance = (NodeAppearance *) _scene->createNode("Appearance"); NodeMaterial *nMaterial = (NodeMaterial *) _scene->createNode("Material"); nShape->geometry(new SFNode(surface)); nShape->appearance(new SFNode(nAppearance)); nAppearance->material(new SFNode(nMaterial)); box = box->addNode(nShape); } ((NodeNurbsGroup *)node)->children((MFNode *)box); return node; } Node* NodeBox::_makeNurbsSurfaces(int surface) { int i,j; NodeNurbsSurface *node = (NodeNurbsSurface *) _scene->createNode("NurbsSurface"); float xPosition = _xSize / 2; float yPosition = _ySize / 2; float zPosition = _zSize / 2; float dx = (float) _xSize / (_nuAreaPoints-1); float dy = (float) _ySize / (_nuAreaPoints-1); float dz = (float) _zSize / (_nvAreaPoints-1); int uOrder = _uOrder; int vOrder = _vOrder; int uDimension = _uDimension; int vDimension = _vDimension; float *uKnots; float *vKnots; float *controlPoints; float *weights; switch (surface) { case 1: uKnots = new float[uDimension + uOrder]; vKnots = new float[vDimension + vOrder]; controlPoints = new float[uDimension * vDimension * 3]; weights = new float[uDimension * vDimension]; _makeKnotvectors(uOrder, uDimension, vOrder, vDimension); for (j = 0; j < vDimension; j++) { for (i = 0; i < uDimension; i++) { controlPoints[(j*uDimension + i)*3 ] = xPosition; controlPoints[(j*uDimension + i)*3 + 1] = (float) +_ySize / 2 - dy * i; controlPoints[(j*uDimension + i)*3 + 2] = (float) -_zSize /2 + dz * (vDimension - 1 - j); weights[j*uDimension + i] = 1.0f; } } break; case 2: uKnots = new float[uDimension + uOrder]; vKnots = new float[vDimension + vOrder]; controlPoints = new float[uDimension * vDimension * 3]; weights = new float[uDimension * vDimension]; _makeKnotvectors(uOrder, uDimension, vOrder, vDimension); for (j = 0; j < vDimension; j++) { for (i = 0; i < uDimension; i++) { controlPoints[(j*uDimension + i)*3 ] = -xPosition; controlPoints[(j*uDimension + i)*3 + 1] = (float) -_ySize / 2 + dy * i; controlPoints[(j*uDimension + i)*3 + 2] = (float) -_zSize /2 + dz * (vDimension - 1 - j); weights[j*uDimension + i] = 1.0f; } } break; case 3: uKnots = new float[uDimension + uOrder]; vKnots = new float[vDimension + vOrder]; controlPoints = new float[uDimension * vDimension * 3]; weights = new float[uDimension * vDimension]; _makeKnotvectors(uOrder, uDimension, vOrder, vDimension); for (j = 0; j < vDimension; j++) { for (i = 0; i < uDimension; i++) { controlPoints[(j*uDimension + i)*3 ] = (float) -_xSize / 2 + dx * i; controlPoints[(j*uDimension + i)*3 + 1] = yPosition; controlPoints[(j*uDimension + i)*3 + 2] = (float) -_zSize /2 + dz * (vDimension - 1 - j); weights[j*uDimension + i] = 1.0f; } } break; case 4: uKnots = new float[uDimension + uOrder]; vKnots = new float[vDimension + vOrder]; controlPoints = new float[uDimension * vDimension * 3]; weights = new float[uDimension * vDimension]; _makeKnotvectors(uOrder, uDimension, vOrder, vDimension); for (j = 0; j < vDimension; j++) { for (i = 0; i < uDimension; i++) { controlPoints[(j*uDimension + i)*3 ] = (float) _xSize / 2 - dx * i; controlPoints[(j*uDimension + i)*3 + 1] = -yPosition; controlPoints[(j*uDimension + i)*3 + 2] = (float) -_zSize /2 + dz * (vDimension - 1 - j); weights[j*uDimension + i] = 1.0f; } } break; case 5: vOrder = _uOrder; vDimension = _uDimension; uKnots = new float[uDimension + uOrder]; vKnots = new float[vDimension + vOrder]; controlPoints = new float[uDimension * vDimension * 3]; weights = new float[uDimension * vDimension]; _makeKnotvectors(uOrder, uDimension, vOrder, vDimension); for (j = 0; j < vDimension; j++) { for (i = 0; i < uDimension; i++) { controlPoints[(j*uDimension + i)*3 ] = (float) _xSize / 2 - dx * i; controlPoints[(j*uDimension + i)*3 + 1] = (float) -_ySize /2 + dy * (vDimension - 1 - j); controlPoints[(j*uDimension + i)*3 + 2] = zPosition; weights[j*uDimension + i] = 1.0f; } } break; case 6: vOrder= _uOrder; vDimension = _uDimension; uKnots = new float[uDimension + uOrder]; vKnots = new float[vDimension + vOrder]; controlPoints = new float[uDimension * vDimension * 3]; weights = new float[uDimension * vDimension]; _makeKnotvectors(uOrder, uDimension, vOrder, vDimension); for (j = 0; j < vDimension; j++) { for (i = 0; i < uDimension; i++) { controlPoints[(j*uDimension + i)*3 ] = (float) -_xSize / 2 + dx * i; controlPoints[(j*uDimension + i)*3 + 1] = (float) -_ySize /2 + dy * (vDimension - 1 - j); controlPoints[(j*uDimension + i)*3 + 2] = -zPosition; weights[j*uDimension + i] = 1.0f; } } break; } for(i=0; i<_uKnots.size(); i++){ uKnots[i] = _uKnots[i]; } for(i=0; i<_vKnots.size(); i++){ vKnots[i] = _vKnots[i]; } node->setField(node->uDimension_Index(), new SFInt32(uDimension)); node->setField(node->vDimension_Index(), new SFInt32(vDimension)); node->uKnot(new MFFloat(uKnots, uDimension + uOrder)); node->vKnot(new MFFloat(vKnots, vDimension + vOrder)); node->setField(node->uOrder_Index(), new SFInt32(uOrder)); node->setField(node->vOrder_Index(), new SFInt32(vOrder)); node->controlPoint(new MFVec3f(controlPoints, uDimension * vDimension * 3)); node->weight(new MFFloat(weights, uDimension * vDimension)); return node; } void NodeBox::_makeKnotvectors(int uOrder, int uDimension, int vOrder, int vDimension) { int i; if(_uKnots.size() > 0){ _uKnots.remove(0, _uKnots.size()-1); } if(_vKnots.size() > 0){ _vKnots.remove(0, _vKnots.size()-1); } for (i = 0; i < uOrder; i++) { _uKnots[i] = 0.0f; _uKnots[uDimension + i] = (float) (uDimension - uOrder + 1); } for (i = 0; i < uDimension - uOrder; i++) { _uKnots[uOrder + i] = (float) (i + 1); } for (i = 0; i < vOrder; i++) { _vKnots[i] = 0.0f; _vKnots[vDimension + i] = (float) (vDimension - vOrder + 1); } for (i = 0; i < vDimension - vOrder; i++) { _vKnots[vOrder + i] = (float) (i + 1); } } void NodeBox::_makeNurbsRectangle(float xSize, float ySize, float zPosition, int nuAreaPoints, int uDegree) { int i; int index1; float dx = xSize / (nuAreaPoints - 1); float dy = ySize / (nuAreaPoints - 1); index1 = 0; for(i=0; igetValue(); Vec3f ret(values[0], values[1], values[2]); ret.scale(-0.5); return ret; } Vec3f NodeBox::getMaxBoundingBox(void) { const float *values = size()->getValue(); Vec3f ret(values[0], values[1], values[2]); ret.scale(0.5); return ret; }