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

NodeSuperExtrusion.cpp

/*
 * NodeSuperExtrusion.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 <stdio.h>
#include "stdafx.h"

#include "NodeSuperExtrusion.h"
#include "Proto.h"
#include "DuneApp.h"
#include "Scene.h"
#include "FieldValue.h"
#include "SFFloat.h"
#include "SFInt32.h"
#include "SFBool.h"
#include "Vec2f.h"

ProtoSuperExtrusion::ProtoSuperExtrusion(Scene *scene)
  : Proto(scene, "SuperExtrusion")
{
    a.set( 
          addExposedField(SFFLOAT, "a", new SFFloat(1.0f)));
    b.set( 
          addExposedField(SFFLOAT, "b", new SFFloat(1.0f)));
    m.set( 
          addExposedField(SFFLOAT, "m", new SFFloat(0.0f)));
    n1.set( 
          addExposedField(SFFLOAT, "n1", new SFFloat(1.0f)));
    n2.set( 
          addExposedField(SFFLOAT, "n2", new SFFloat(1.0f)));
    n3.set( 
          addExposedField(SFFLOAT, "n3", new SFFloat(1.0f)));
    border.set( 
          addExposedField(SFFLOAT, "border", new SFFloat(M_PI),
                          new SFFloat(-M_PI), new SFFloat(M_PI)));

    creaseAngle.set( 
          addField(SFFLOAT, "creaseAngle", new SFFloat(0.7854f), 
                   new SFFloat(0.0f)));
    superTessellation.set(
          addExposedField(SFINT32, "superTessellation", new SFInt32(0)));
    spineTessellation.set(
          addExposedField(SFINT32, "spineTessellation", new SFInt32(0)));

    controlPoint.set(
          addExposedField(MFVEC3F, "controlPoint", new MFVec3f()));
    weight.set(
          addExposedField(MFDOUBLE, "weight", new MFDouble(), new SFFloat(0.0f)));
    knot.set(
          addField(MFDOUBLE, "knot", new MFDouble()));
    order.set(
          addField(SFINT32, "order", new SFInt32(3), new SFInt32(2)));

    beginCap.set(
          addField(SFBOOL, "beginCap", new SFBool(true)));
    endCap.set(
          addField(SFBOOL, "endCap", new SFBool(true)));

    float   values3[] = { 1.0, 1.0 };
    float      *v = new float[2];  
    memcpy(v, values3, 2 * sizeof(float));
    scale.set(
          addField(MFVEC2F, "scale", new MFVec2f(v, 2), new SFFloat(0.0f)));
}

Node *
ProtoSuperExtrusion::create(Scene *scene)
{
    return new NodeSuperExtrusion(scene, this); 
}

NodeSuperExtrusion::NodeSuperExtrusion(Scene *scene, Proto *def)
  : Node(scene, def)
{
    _extrusionDirty = true;
    _extrusion = (NodeExtrusion *) scene->createNode("Extrusion");
    _nurbsCurve = (NodeNurbsCurve *) scene->createNode("NurbsCurve");
}

NodeSuperExtrusion::~NodeSuperExtrusion()
{
    delete _extrusion;
    delete _nurbsCurve;
}

static float superFormula(float angle, float a, float b, float m, 
                          float n1, float n2, float n3)
    {
    float f = m * angle / 4.0;
    float c = cos(f);
    float s = sin(f);
    return pow(pow(fabs(c / a), n2) + pow(fabs(s / b), n3), -1.0 / n1);
    }

void
NodeSuperExtrusion::createExtrusion()
{
    if (_extrusion == NULL)
        _extrusion = (NodeExtrusion *) _scene->createNode("Extrusion");

    if (_nurbsCurve == NULL)
        _nurbsCurve = (NodeNurbsCurve *) _scene->createNode("NurbsCurve");

    int           superTess = superTessellation()->getValue();
    int           spineTess = spineTessellation()->getValue();

    if (superTess <= 0) superTess = 32;
    if (spineTess <= 0) spineTess = 32;

    superTess++;

    if (superTess < 3) return;

    int     size = superTess;
    Vec2f *vert = new Vec2f[size];

    float low = -M_PI ;
    float high = border()->getValue();
    
    float inc1 = (high - low) / (superTess-1);
    if (inc1 < EPSILON) return;
    int a1;
    float fa = a()->getValue();
    float fb = b()->getValue();
    float fm = m()->getValue();
    float fn1 = n1()->getValue();
    float fn2 = n2()->getValue();
    float fn3 = n3()->getValue();
    Array<float> r1(superTess);
    Array<float> c1(superTess);
    Array<float> s1(superTess);
    for (a1 = 0; a1 < superTess; a1++) {
        float angle1 = -M_PI + a1 * inc1;
        r1[a1] = superFormula(angle1, fa, fb, fm, fn1, fn2, fn3);
        c1[a1] = cos(angle1);
        s1[a1] = sin(angle1);
    }
    int index = 0;
    for (a1 = 0; a1 < superTess; a1++) {
        vert[index].x = r1[a1]*c1[a1];
        vert[index].y = r1[a1]*s1[a1];
        index++;
    }

    int i;

    _extrusion->crossSection(new MFVec2f((float *) vert, size * 2));
    
    bool bsolid = false;
    if ((high == M_PI) && beginCap()->getValue() && endCap()->getValue())
        bsolid = true;

    _extrusion->solid(new SFBool(bsolid));
    _extrusion->convex(new SFBool(false));
    _extrusion->creaseAngle(new SFFloat(creaseAngle()->getValue()));
    _extrusion->beginCap(new SFBool(beginCap()->getValue()));
    _extrusion->endCap(new SFBool(endCap()->getValue()));
    _nurbsCurve->tessellation(new SFInt32(spineTessellation()->getValue()));
    float *points = new float[controlPoint()->getSize()];
    for (i = 0; i < controlPoint()->getSize(); i++)
         points[i] = controlPoint()->getValues()[i];
    _nurbsCurve->controlPoint(new MFVec3f(points, controlPoint()->getSize()));
    float *weights = new float[weight()->getSize()];
    for (i = 0; i < weight()->getSize(); i++)
         weights[i] = weight()->getValues()[i];
    _nurbsCurve->weight(new MFFloat(weights, weight()->getSize()));
    float *knots = new float[knot()->getSize()];
    for (i = 0; i < knot()->getSize(); i++)
         knots[i] = knot()->getValues()[i];
    _nurbsCurve->knot(new MFFloat(knots, knot()->getSize()));
    _nurbsCurve->order(new SFInt32(order()->getValue()));
    const Vec3f *chain = _nurbsCurve->getChain();
    int chainLength = _nurbsCurve->getChainLength();
    float *fchain = new float[chainLength * 3];
    for (i = 0; i < chainLength; i++) {
         fchain[i * 3    ] = chain[i].x;
         fchain[i * 3 + 1] = chain[i].y;
         fchain[i * 3 + 2] = chain[i].z;
    }   
    _extrusion->spine(new MFVec3f(fchain, chainLength * 3));
    if (scale()->getSFSize() > 0) {
        float *scales;
        int scaleLen = scale()->getSFSize();
        if (scaleLen == 1)
            scales = new float[2];
        else
           scales = new float[2 * (spineTess + 1)];
        scales[0] = scale()->getValues()[0];
        scales[1] = scale()->getValues()[1];
        if (scaleLen > 1) {
            float tess_inc = 1.0 / (spineTess);
            float scale_inc = 1.0 / (scaleLen - 1);
            float scale_left = 0.0;
            int scale_next_index = 1;
            for (i = 1; i <= spineTess; i++) {
                float left_scale_x; 
                left_scale_x = scale()->getValues()[scale_next_index * 2 - 2];
                float scale_diff_x;
                scale_diff_x = scale()->getValues()[scale_next_index * 2 + 0] - 
                               left_scale_x;
                scales[i * 2 + 0] = left_scale_x + scale_diff_x * 
                                    ((i * tess_inc - scale_left) / scale_inc);

                float left_scale_y; 
                left_scale_y = scale()->getValues()[scale_next_index * 2 - 1];
                float scale_diff_y;
                scale_diff_y = scale()->getValues()[scale_next_index * 2 + 1] - 
                               left_scale_y;
                scales[i * 2 + 1] = left_scale_y + scale_diff_y * 
                                    ((i * tess_inc - scale_left) / scale_inc);

                if ((i * tess_inc) >= (scale_next_index * scale_inc)) {
                    scale_next_index++;
                    scale_left += scale_inc;
                }              
            }
        }
        _extrusion->scale(new MFVec2f(scales, scaleLen == 1 ? 2 : 
                                              (spineTess + 1) * 2));
    }
    _extrusionDirty = false;
}

bool
NodeSuperExtrusion::writeEXTERNPROTO(int f)
{
    RET_ONERROR( mywritestr(f ,"EXTERNPROTO SuperExtrusion[\n") )    
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," exposedField SFFloat a\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," exposedField SFFloat b\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," exposedField SFFloat m\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," exposedField SFFloat n1\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," exposedField SFFloat n2\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," exposedField SFFloat n3\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," exposedField SFFloat border\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," field SFFloat creaseAngle\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," exposedField SFInt32 superTessellation\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," exposedField SFInt32 spineTessellation\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," exposedField MFVec3f controlPoint\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," exposedField MFFloat weight\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," field MFFloat knot\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," field SFInt32 order\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," field SFBool  beginCap\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," field SFBool  endCap\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," exposedField  MFVec2f scale\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," ]\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ,"[\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ,"# \"") )
    RET_ONERROR( mywritestr(f ,"SuperExtrusionPROTO.wrl") )
    RET_ONERROR( mywritestr(f ,"\"\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ,"\"") )
    char *dunedocs = getenv("DUNEDOCS");
    if (dunedocs != NULL) {
        RET_ONERROR( mywritestr(f ,dunedocs) )
        RET_ONERROR( mywritestr(f ,"/scriptedNodes") )
    }
#ifdef HAVE_SCRIPTED_NODES_PROTO_URL
    else
        RET_ONERROR( mywritestr(f ,HAVE_SCRIPTED_NODES_PROTO_URL) )
#endif
    RET_ONERROR( mywritestr(f ,"/") )
    RET_ONERROR( mywritestr(f ,"SuperExtrusionPROTO.wrl") )
    RET_ONERROR( mywritestr(f ,"\"\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," \"http://www.csv.ica.uni-stuttgart.de/vrml/dune/docs/scriptedNodes/SuperExtrusionPROTO.wrl\"\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ,"]\n") )
    TheApp->incSelectionLinenumber();
    return true;
}

int             
NodeSuperExtrusion::write(int filedes, int indent) 
{
    if (_scene->isPureVRML97()) {
        Node *node = toExtrusion();
        if (node == NULL) 
           return 1;
        RET_ONERROR( node->write(filedes, indent) )
        node->unref();
    } else
        RET_ONERROR( NodeData::write(filedes, indent) )
    return 0;
}

void
NodeSuperExtrusion::setField(int index, FieldValue *value)
{
    _extrusionDirty = true;
    Node::setField(index, value);
}

void
NodeSuperExtrusion::draw()
{
    if (_extrusionDirty) {
        createExtrusion();
        _extrusionDirty = false;
    }

    if (!_extrusion) return;

    _extrusion->draw();
}

void  
NodeSuperExtrusion::drawHandles()
{
    if (_extrusionDirty) {
        createExtrusion();
        _extrusionDirty = false;
    }

    if (!_extrusion) return;

    _nurbsCurve->drawHandles();
}

Vec3f
NodeSuperExtrusion::getHandle(int handle, int *constraint,
                      int *field)
{
    *constraint = CONSTRAIN_NONE;
    *field = controlPoint_Index() ;

    if (handle >= 0 && handle < controlPoint()->getSize() / 3) {
      Vec3f ret((Vec3f)controlPoint()->getValue(handle) / 
                   weight()->getValue(handle));
        return ret;
    } else {
        return Vec3f(0.0f, 0.0f, 0.0f);
    }
}


void
NodeSuperExtrusion::setHandle(int handle, const Vec3f &v) 
{
    MFVec3f    *oldValue = controlPoint();
    MFVec3f    *newValue = (MFVec3f *)oldValue->copy();

    if (handle >= 0 && handle < oldValue->getSize() / 3) {
        Vec3f     v2 = v * weight()->getValue(handle);       
        _extrusionDirty = true;
      newValue->setValue(handle * 3, v2.x);
      newValue->setValue(handle * 3+1, v2.y);
      newValue->setValue(handle * 3+2, v2.z);
      _scene->setField(this, controlPoint_Index(), newValue);
    }
}

Node *
NodeSuperExtrusion::toExtrusion(void)
{
    if (_extrusionDirty) {
        createExtrusion();
        _extrusionDirty = false;
    }

    if (!_extrusion) 
        return NULL;

    return _extrusion->copy();
}

Vec3f   
NodeSuperExtrusion::getMinBoundingBox(void)
{
    if (_extrusionDirty) {
        createExtrusion();
        _extrusionDirty = false;
    }
 
    return _extrusion->getMinBoundingBox();
}

Vec3f   
NodeSuperExtrusion::getMaxBoundingBox(void)
{
    if (_extrusionDirty) {
        createExtrusion();
        _extrusionDirty = false;
    }
 
    return _extrusion->getMaxBoundingBox();
}

void
NodeSuperExtrusion::flip(int index)
{
    if (controlPoint())
        controlPoint()->flip(index);
    _extrusionDirty = true;    
}


Node   *
NodeSuperExtrusion::toNurbsCurve(void)
{
  NodeNurbsCurve *node = (NodeNurbsCurve *) _scene->createNode("NurbsCurve");
  
  int i;
  float *tmpControlPoints = new float[controlPoint()->getSize()];
  float *tmpWeights = new float[weight()->getSize()];
  float *tmpKnots = new float[knot()->getSize()];
  int tmpOrder = order()->getValue();  
  
  for(i=0; i<(controlPoint()->getSize()); i++){
    tmpControlPoints[i] = controlPoint()->getValues()[i];
  }

  for(i=0; i<(weight()->getSFSize()); i++){
    tmpWeights[i] = weight()->getValue(i);
  }
  
  for(i=0; i<(knot()->getSFSize()); i++){
    tmpKnots[i] = knot()->getValue(i);
  }
    
  node->setField(node->tessellation_Index(), 
                 new SFInt32(spineTessellation()->getValue()));
  node->knot(new MFFloat(tmpKnots, knot()->getSFSize()));
  node->setField(node->order_Index(), new SFInt32(tmpOrder));
  node->controlPoint(new MFVec3f(tmpControlPoints, controlPoint()->getSize()));
  node->weight(new MFFloat(tmpWeights, weight()->getSFSize()));

  return node;
}


Generated by  Doxygen 1.6.0   Back to index