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

NodeSphere.cpp

/*
 * NodeSphere.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 "NodeSphere.h"
#include "Proto.h"
#include "FieldValue.h"
#include "Node.h"
#include "Scene.h"
#include "SFFloat.h"
#include "MFNode.h"
#include "SFNode.h"
#include "SFInt32.h"
#include "MFFloat.h"
#include "MFVec3f.h"
#include "NurbsArc.h"
#include "NurbsMakeRevolvedSurface.h"
#include "NodeNurbsSurface.h"
#include "RenderState.h"
#include "Util.h"
#include "SFVec3f.h"

ProtoSphere::ProtoSphere(Scene *scene)
  : Proto(scene, "Sphere")
{
    radius.set(
          addField(SFFLOAT, "radius", new SFFloat(1.0F), new SFFloat(0.0f)));
}

Node *
ProtoSphere::create(Scene *scene)
{ 
    return new NodeSphere(scene, this); 
}

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

void NodeSphere::draw()
{
    GLUquadricObj   *obj = gluNewQuadric();
    if (glIsEnabled(GL_TEXTURE_2D)) gluQuadricTexture(obj, GL_TRUE);
    glPushMatrix();
    glRotatef(-90.0f, 1.0f, 0.0f, 0.0f);

    gluSphere(obj, radius()->getValue(), 16, 8);

    glPopMatrix();

    gluDeleteQuadric(obj);
}


void

NodeSphere::drawHandles()
{
    float fradius = radius()->getValue();
    RenderState state;
             
    glPushMatrix();
    glScalef(fradius*1.0f,fradius*1.0f,fradius*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 < 6; i++) {
      glLoadName(i);
      state.drawHandle(spereCorners[i]);
    }
    state.endDrawHandles();
    glPopName();
    glPopAttrib();
    glPopMatrix(); 
}

Vec3f
NodeSphere::getHandle(int handle, int *constraint , int *field)
{
    *field = 0;
    float fradius = radius()->getValue();
    Vec3f ps;
    ps.x = fradius;
    ps.y = fradius;
    ps.z = fradius;
    switch (handle) {               
      case STLF: case STLB:
      return Vec3f(ps) * Vec3f(spereCorners[handle]) * 1.0f; //z-direction
      case SBRB:case SBLB:
      return Vec3f(ps) * Vec3f(spereCorners[handle]) * 1.0f; //y-direction
      case STRB:case SBLF:
      return Vec3f(ps) * Vec3f(spereCorners[handle]) * 1.0f; //x-direction
      default:
      assert(0);
      return Vec3f(1.0f, 1.0f, 1.0f);
    } 
}

void 
NodeSphere::setHandle(int handle, const Vec3f &v)
{
    switch (handle) {
      case STLF: case STLB:
      _scene->setField(this, radius_Index(),new SFFloat(v.z*1.0f*Vec3f(spereCorners[handle]).z)); 
      break;
      case SBRB:case SBLB:
        _scene->setField(this, radius_Index(),new SFFloat(v.y*1.0f*Vec3f(spereCorners[handle]).y));
      break;
      case STRB:case SBLF:
      _scene->setField(this, radius_Index(),new SFFloat(v.x*1.0f*Vec3f(spereCorners[handle]).x)); 
      break;
    } 
}

Node*
NodeSphere::toNurbs(int narcslong,  int narcslat, int uDegree, int vDegree)
{   
  NodeNurbsSurface *node = (NodeNurbsSurface *) _scene->createNode(
                                 "NurbsSurface");
  float radius = ((SFFloat *) getField(0))->getValue();
  
  /*meaning of most important variables

    int narcslong ->number of circular arc segments from pole to pole 
                    (longitudinal)
    int narcslat  -> number of circular arc segments in lateral direction
    int vDegree -> degree in direction v, currently limited to 2
    int uDegree -> degree in direction u, currently limited to 2
  */

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

  int i;
  
  float arc = 180;
  Vec3f PS, P1, P2;
  
  PS.x = 0;
  PS.y = -radius;
  PS.z = 0;

  P1.x = P2.x = 0;
  P1.y = P2.y = 0;
  P1.z = 0;
  P2.z = 1;

  NurbsArc tmpArc(narcslong, arc, PS, P1, P2, vDegree);
  
  Vec3f *longitudinalArc = new Vec3f[tmpArc.getPointSize()];
  float *tmpWeights = new float[tmpArc.getPointSize()];
  
  //load generatrix
  for (i=0; i<tmpArc.getPointSize(); i++){
    longitudinalArc[i] = tmpArc.getControlPoints(i);
    tmpWeights[i] = tmpArc.getWeights(i);    
  }

  float *vKnots = new float[tmpArc.getKnotSize()];
  
  //load v-knotvector
  for (i=0; i<(tmpArc.getKnotSize()); i++){
    vKnots[i] = tmpArc.getKnots(i);
  }

  //rotate generatrix 
  arc = 360;
  P1.x = P2.x = 0;
  P1.z = P2.z = 0;
  P1.y = 0;
  P2.y = 1;

  NurbsMakeRevolvedSurface nurbsSphere(longitudinalArc, tmpWeights, tmpArc.getPointSize(), narcslat, arc, uDegree, P1, P2);
  if (!nurbsSphere.isValid())
      return NULL;

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

  int max_i = nurbsSphere.getPointSize();
  for(i=0; i<max_i; i++){
    controlPoints[i] = nurbsSphere.getControlPoints(i);
  }
  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 {
    max_i = nurbsSphere.getKnotSize();
    for(i=0; i<max_i; i++){
      uKnots[i] = nurbsSphere.getKnots(i);
    }
  }
  if (vDegree == 1) {
    //set v-knotvektor
    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);  
    } 
  }  
  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
NodeSphere::getMinBoundingBox(void) 
{ 
  float fradius = radius()->getValue();
  Vec3f ret(- fradius, - fradius, - fradius);
  return ret;
}

Vec3f   
NodeSphere::getMaxBoundingBox(void) 
{ 
  float fradius = radius()->getValue();
  Vec3f ret(fradius, fradius, fradius);
  return ret;
}


Generated by  Doxygen 1.6.0   Back to index