Logo Search packages:      
Sourcecode: whitedune version File versions  Download package

NodeBox.cpp

/*
 * 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 <stdio.h>
#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; i<uDimension * vDimension * 3; i++){
    controlPoints[i]=0.0f;
  }

  //surface orthogonal z-axis
  for(j=0; j<nzAreaPoints-1; j++){
    zPosition = zSize / 2;
    tmpxSize = j * xSize / (nzAreaPoints-1);
    tmpySize = j * ySize / (nzAreaPoints-1);
    _makeNurbsRectangle(tmpxSize, tmpySize, zPosition, nuAreaPoints, uDegree);
    for(i=0; i<_rectangle.size(); i++){
      controlPoints[(j*uDimension + i)*3    ] = _rectangle[i].x;  
      controlPoints[(j*uDimension + i)*3 + 1] = _rectangle[i].y;
      controlPoints[(j*uDimension + i)*3 + 2] = _rectangle[i].z;  
    }
    index1++;
  }

  //make sharp edge
  tmpindex = 0;
  for(j=index1; j<index1+vDegree-1; j++){
    _makeNurbsRectangle(xSize, ySize, zPosition, nuAreaPoints, uDegree);
    for(i=0; i<_rectangle.size(); i++){
      controlPoints[(j*uDimension + i)*3    ] = _rectangle[i].x;  
      controlPoints[(j*uDimension + i)*3 + 1] = _rectangle[i].y;
      controlPoints[(j*uDimension + i)*3 + 2] = _rectangle[i].z;  
    }
    tmpindex++;
  }            
  index1 = index1 + tmpindex;

  //surfaces in direction of z-axis
  tmpindex = 0;
  for(j=index1, index2=0; j<index1+nvAreaPoints; j++, index2++){  
    zPosition = zSize / 2 - index2 * dz;
    _makeNurbsRectangle(xSize, ySize, zPosition, nuAreaPoints, uDegree);
    for(i=0; i<_rectangle.size(); i++){
      controlPoints[(j*uDimension + i)*3    ] = _rectangle[i].x;  
      controlPoints[(j*uDimension + i)*3 + 1] = _rectangle[i].y;
      controlPoints[(j*uDimension + i)*3 + 2] = _rectangle[i].z;  
    }
    tmpindex++;
  }
  index1 = index1 + tmpindex;

  //make sharp edge
  tmpindex = 0;
  for(j=index1; j<index1+vDegree-1; j++){
    zPosition = -zSize / 2;
    _makeNurbsRectangle(xSize, ySize, zPosition, nuAreaPoints, uDegree);
    for(i=0; i<_rectangle.size(); i++){
      controlPoints[(j*uDimension + i)*3    ] = _rectangle[i].x;  
      controlPoints[(j*uDimension + i)*3 + 1] = _rectangle[i].y;
      controlPoints[(j*uDimension + i)*3 + 2] = _rectangle[i].z;  
    }
    tmpindex++;
  }              
  index1 = index1 + tmpindex;
  
  //surface orthogonal z-axis
  index2 = 0;
  tmpindex = 0;
  for(j=index1, index2=1; j<index1+nzAreaPoints-1; j++, index2++){
    tmpxSize = xSize - index2 * xSize / (nzAreaPoints-1);
    tmpySize = ySize - index2 * ySize / (nzAreaPoints-1);
    _makeNurbsRectangle(tmpxSize, tmpySize, zPosition, nuAreaPoints, uDegree);
    for(i=0; i<_rectangle.size(); i++){
      controlPoints[(j*uDimension + i)*3    ] = _rectangle[i].x;  
      controlPoints[(j*uDimension + i)*3 + 1] = _rectangle[i].y;
      controlPoints[(j*uDimension + i)*3 + 2] = _rectangle[i].z;  
    }
    tmpindex++;
  }              
  index1 = index1 + tmpindex;

  _makeKnotvectors(uOrder, uDimension, vOrder, vDimension);

  for(i=0; i<_uKnots.size(); i++){
    uKnots[i] = _uKnots[i];
  }
  for(i=0; i<_vKnots.size(); i++){
    vKnots[i] = _vKnots[i];
  }  
  
  for(i=0; i<uDimension*vDimension; i++){
    weights[i] = 1.0f;
  }

  node->setField(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; i<uDegree-1; i++){
    _rectangle[index1].x = xSize / 2;           
    _rectangle[index1].y = ySize / 2;           
    _rectangle[index1].z = zPosition;           
    index1++;
  }   
  for(i=0; i<nuAreaPoints; i++){
    _rectangle[index1].x = xSize / 2;  
    _rectangle[index1].y = ySize / 2 - i * dy;           
    _rectangle[index1].z = zPosition;           
    index1++;
  }
  for(i=0; i<uDegree-1; i++){
    _rectangle[index1].x = xSize / 2;          
    _rectangle[index1].y = - ySize / 2;           
    _rectangle[index1].z = zPosition;           
    index1++;
  }
  for(i=1; i<nuAreaPoints; i++){
    _rectangle[index1].x = xSize / 2 - i * dx;          
    _rectangle[index1].y = - ySize / 2;            
    _rectangle[index1].z = zPosition;
    index1++;
  }    
  for(i=0; i<uDegree-1; i++){
    _rectangle[index1].x = - xSize / 2;          
    _rectangle[index1].y = - ySize / 2;          
    _rectangle[index1].z = zPosition;
    index1++;
    }    
  for(i=1; i<nuAreaPoints; i++){
    _rectangle[index1].x = - xSize / 2;              
    _rectangle[index1].y = - ySize / 2 + i * dy;         
    _rectangle[index1].z = zPosition;
    index1++;
  }    
  for(i=0; i<uDegree-1; i++){
    _rectangle[index1].x = - xSize / 2;          
    _rectangle[index1].y = ySize / 2;         
    _rectangle[index1].z = zPosition;
    index1++;
  }    
  for(i=1; i<nuAreaPoints; i++){
    _rectangle[index1].x = - xSize / 2 + i * dx;          
    _rectangle[index1].y = ySize / 2;             
    _rectangle[index1].z = zPosition;
    index1++;
  }        
}

Vec3f
NodeBox::getMinBoundingBox(void) 
{ 
  const float *values = size()->getValue();
  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;
}


Generated by  Doxygen 1.6.0   Back to index