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

NodeCone.cpp

/*
 * NodeCone.cpp
 *
 * Copyright (C) 1999 Stephen F. White
 *               2003 Th. Rothermel
 *               2004 Wu Qingwei
 *
 * 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 "NodeCone.h"
#include "Proto.h"
#include "FieldValue.h"
#include "Scene.h"
#include "SFFloat.h"
#include "SFBool.h"
#include "MFNode.h"
#include "SFNode.h"
#include "SFInt32.h"
#include "MFFloat.h"
#include "MFVec3f.h"
#include "NurbsMakeRevolvedSurface.h"
#include "NodeNurbsSurface.h"
#include "RenderState.h"
#include "SFVec3f.h"
#include "Util.h"
#include "MFNode.h"

ProtoCone::ProtoCone(Scene *scene)
  : Proto(scene, "Cone")
{
    bottomRadius.set(
          addField(SFFLOAT, "bottomRadius", new SFFloat(1.0f), 
                   new SFFloat(0.0f)));
    height.set(
          addField(SFFLOAT, "height", new SFFloat(2.0f), new SFFloat(0.0f)));
    side.set(
          addField(SFBOOL, "side", new SFBool(true)));
    bottom.set(
          addField(SFBOOL, "bottom", new SFBool(true)));
}

Node *ProtoCone::create(Scene *scene)
{ 
    return new NodeCone(scene, this); 
}

NodeCone::NodeCone(Scene *scene, Proto *def)
  : Node(scene, def)
{
}

void NodeCone::draw()
{
    float fbottomRadius = bottomRadius()->getValue();
    float fheight = height()->getValue();

    GLUquadricObj   *obj = gluNewQuadric();
    if (glIsEnabled(GL_TEXTURE_2D)) gluQuadricTexture(obj, GL_TRUE);

    glPushMatrix();
    glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);
    glTranslatef(0.0f, 0.0f, -fheight * 0.5f);
    if (side()->getValue()) {
      gluCylinder(obj, fbottomRadius, 0.0f, fheight, 16, 2);
    }
    if (bottom()->getValue()) {
      glPushMatrix();
      glRotatef(180.0f, 1.0f, 0.0f, 0.0f);
      gluDisk(obj, 0.0f, fbottomRadius, 20, 1);
      glPopMatrix();
    }
    glPopMatrix();

    gluDeleteQuadric(obj);
}

void NodeCone::drawHandles()
{

    RenderState state;
      
    float fheight = height()->getValue();
    float fbottomRadius = bottomRadius()->getValue(); 
   
    glPushMatrix();

    glScalef(fbottomRadius * 1.0f,fheight * 0.5f, fbottomRadius * 1.0f );
    glPushAttrib(GL_LIGHTING);
    glDisable(GL_LIGHTING);
    glPushName(0);
    Util::myGlColor3f(1.0f, 1.0f, 1.0f);
    state.startDrawHandles();    
    for (int i = 0; i < 5; i++) {
      glLoadName(i);
      state.drawHandle(ConeCorners[i]);
    }
    state.endDrawHandles();
    glPopName();
    glPopAttrib();
    glPopMatrix();


}

Vec3f
NodeCone::getHandle(int handle,int* constrait, int* field)
{     
    float fheight = height()->getValue();
    float fbottomRadius = bottomRadius()->getValue();
  
    switch (handle) {
      case COBLB:
        *field=1;
        return Vec3f(1.0f*fbottomRadius,1.0f*fheight,1.0f*fbottomRadius) * Vec3f(ConeCorners[handle]) * 0.5f;
      case COBRB: case COTRB: 
      *field=0;      
        return Vec3f(1.0f*fbottomRadius,0.0f,1.0f*fbottomRadius) * Vec3f(ConeCorners[handle]) * 1.0f;
      case COTLB: case COBLF:         
      *field=0;      
        return Vec3f(1.0f*fbottomRadius,0.0f,1.0f*fbottomRadius) * Vec3f(ConeCorners[handle]) * 1.0f;
      default:
      assert(0);
      return Vec3f(1.0f, 1.0f, 1.0f);
    }
      
}

void 
NodeCone::setHandle(int handle,const Vec3f &v)
{
            
    switch (handle) {
      case COBLB: 
      _scene->setField(this,height_Index(),new SFFloat(v.y*2.0f*Vec3f(ConeCorners[handle]).y));
      break; 
      case COBRB: case COTRB:
      _scene->setField(this,bottomRadius_Index(),new SFFloat(v.x*1.0f*Vec3f(ConeCorners[handle]).x));
      break;
      case COTLB: case COBLF:
       _scene->setField(this,bottomRadius_Index(),new SFFloat(v.z*1.0f*Vec3f(ConeCorners[handle]).z));
       break;
     }
}

Node*
NodeCone::toNurbs(int nshell, int narea, int narcs, int uDegree, int vDegree)
{   
  NodeNurbsSurface *node = (NodeNurbsSurface *)
                            _scene->createNode("NurbsSurface");
  float fbottomRadius = bottomRadius()->getValue();
  float fheight = height()->getValue();
  int iside = side()->getValue();
  int ibottom = bottom()->getValue();

  /*At the edge (shell to bottom area) there are p circles at the same 
    position to achieve sharp edge  
  
    meaning of the main variables:

    int narcs ->number of circular arc segments, cone consists of
    int nshell -> number of controlpoints on shell in direction of axis
    int narea -> number of controlpoints on bottom area in direction of radius
    int vDegree -> degree in direction v
    int uDegree -> degree in direction u, currently limited to 2
  */

  int vOrder = vDegree +1;
  int uOrder = uDegree +1;

  int vDimension;
  if(iside==1){ 
    vDimension = (ibottom * (narea + vDegree - 2)) + nshell;
  }
  else{
    vDimension = (ibottom * narea);
  }

  float *vKnots = new float[vDimension + vOrder];

  Vec3f *generatrix = new Vec3f[vDimension];
  float *tmpWeights = new float[vDimension]; 

  int i,j;
  int max_i; 
  float y;  
  
  //load generatrix
  //shell
  float stepdown;
  float stepradius;
  if (iside==1){
    y = fheight / 2; //start at apex
    stepdown = fheight / (nshell - 1);
    stepradius = fbottomRadius / (nshell - 1); 
    for(i=0; i<(iside*nshell); i++){
      generatrix[i].x = i * stepradius;
      generatrix[i].y = y;
      generatrix[i].z = 0;
      y = y - stepdown;
    }
  }
  //bottom area
  if (ibottom==1){
    y = - fheight / 2;
    stepradius = fbottomRadius / (narea - 1);
    if(iside==1){
      for(i=(iside*nshell), j=1; i<((iside*nshell)+vDegree-2); i++, j++){
      generatrix[i].x = (narea - 1) * stepradius;
      generatrix[i].y = y; 
      generatrix[i].z = 0;
      }
      for(i=(nshell+vDegree-2), j=1; i<(nshell+narea+vDegree-2); i++, j++){
      generatrix[i].x = (narea - j) * stepradius;
      generatrix[i].y = y;   
      generatrix[i].z = 0;
      }
    }
    else{
      for(i=0, j=1; i<narea; i++, j++){
      generatrix[i].x = (narea - j) * stepradius;
      generatrix[i].y = y;
      generatrix[i].z = 0;
      }
    }
  }

  //weights
  for(i=0; i<vDimension; i++){
    tmpWeights[i] = 1;
  }
  //v-knotvector
  for(i=0; i<vOrder; i++){
    vKnots[i] = 0.0f;
    vKnots[i+vDimension] = (float) (vDimension - vOrder +1);
  }
  for(i=0; i<(vDimension-vOrder); i++){
    vKnots[i+vOrder] = (float) (i + 1);  
  } 
  //rotate generatrix. 
  float arc = 360;
  Vec3f P1, P2; 
  P1.x = P2.x = 0;
  P1.z = P2.z = 0;
  P1.y = 0;
  P2.y = -1;

  NurbsMakeRevolvedSurface nurbsSphere(generatrix, tmpWeights, vDimension, narcs, arc, uDegree, P1, P2);   
  if (!nurbsSphere.isValid())
      return NULL;

  float *controlPoints = new float[nurbsSphere.getPointSize()];
  float *weights = new float[nurbsSphere.getWeightSize()];
  int uDimension = nurbsSphere.getWeightSize() / vDimension;
  float *uKnots = new float[uDimension + uOrder]; 

  //get control points
  max_i = nurbsSphere.getPointSize();
  for(i=0; i<max_i; i++){
    controlPoints[i] = nurbsSphere.getControlPoints(i);
  }
  //get weights
  max_i = nurbsSphere.getWeightSize();
  for(i=0; i<max_i; i++){
    weights[i] = nurbsSphere.getWeights(i);
  }

  if (uDegree == 1){
    //set u-knotvektor
    for(i=0; i<uOrder; i++){
      uKnots[i] = 0.0f;
      uKnots[i+uDimension] = (float) (uDimension - uOrder +1);
    }
    for(i=0; i<(uDimension-uOrder); i++){
      uKnots[i+uOrder] = (float) (i + 1);  
    } 
  }  
  else {
    //get u-knotvektor
    max_i = nurbsSphere.getKnotSize();
    for(i=0; i<max_i; i++){
       uKnots[i] = nurbsSphere.getKnots(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; 
}

Vec3f
NodeCone::getMinBoundingBox(void) 
{ 
  float fheight = height()->getValue() * 0.5;
  Vec3f ret(-bottomRadius()->getValue(), -fheight, -bottomRadius()->getValue()); 
  if (!(side()->getValue())) 
      if (!(bottom()->getValue())) {
          ret.x = 0;
          ret.y = 0;
          ret.z = 0;
      }
  return ret;
}

Vec3f   
NodeCone::getMaxBoundingBox(void) 
{ 
  float fheight = height()->getValue() * 0.5;
  Vec3f ret(bottomRadius()->getValue(), fheight, bottomRadius()->getValue()); 
  if (!(side()->getValue())) 
      if (bottom()->getValue())
          ret.y = -fheight;
      else {
          ret.x = 0;
          ret.y = 0;
          ret.z = 0;
      }
  return ret;
}

void
NodeCone::flip(int index)
{
    if (index == 1) {
        // cone can not handle a y-flip, convert to NurbsSurface
        Node *nurbs =_scene->convertConeToNurbs(this);
        if (nurbs != NULL)
            nurbs->flip(index);
    }
}




Generated by  Doxygen 1.6.0   Back to index