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

NodeSuperShape.cpp

/*
 * NodeSuperShape.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 "NodeSuperShape.h"
#include "Proto.h"
#include "DuneApp.h"
#include "FieldValue.h"
#include "Scene.h"
#include "Mesh.h"
#include "SFFloat.h"
#include "SFInt32.h"
#include "SFBool.h"
#include "NodeIndexedFaceSet.h"
#include "NodeCoordinate.h"
#include "NodeNormal.h"
#include "NodeTextureCoordinate.h"
#include "NodeNurbsSurface.h"

ProtoSuperShape::ProtoSuperShape(Scene *scene)
  : Proto(scene, "SuperShape")
{
    ua.set( 
          addExposedField(SFFLOAT, "ua", new SFFloat(1.0f)));
    ub.set( 
          addExposedField(SFFLOAT, "ub", new SFFloat(1.0f)));
    um.set( 
          addExposedField(SFFLOAT, "um", new SFFloat(0.0f)));
    un1.set( 
          addExposedField(SFFLOAT, "un1", new SFFloat(1.0f)));
    un2.set( 
          addExposedField(SFFLOAT, "un2", new SFFloat(1.0f)));
    un3.set( 
          addExposedField(SFFLOAT, "un3", new SFFloat(1.0f)));

    va.set( 
          addExposedField(SFFLOAT, "va", new SFFloat(1.0f)));
    vb.set( 
          addExposedField(SFFLOAT, "vb", new SFFloat(1.0f)));
    vm.set( 
          addExposedField(SFFLOAT, "vm", new SFFloat(0.0f)));
    vn1.set( 
          addExposedField(SFFLOAT, "vn1", new SFFloat(1.0f)));
    vn2.set( 
          addExposedField(SFFLOAT, "vn2", new SFFloat(1.0f)));
    vn3.set( 
          addExposedField(SFFLOAT, "vn3", new SFFloat(1.0f)));

    border.set( 
          addExposedField(SFFLOAT, "border", new SFFloat(M_PI / 2.0),
                          new SFFloat(-M_PI / 2.0), new SFFloat(M_PI / 2.0)));

    creaseAngle.set( 
          addField(SFFLOAT, "creaseAngle", new SFFloat(0.7854f), 
                   new SFFloat(0.0f)));
    texCoord.set(
          addExposedField(SFNODE, "texCoord", new SFNode(NULL), 
                          TEXTURE_COORDINATE_NODE));
    uTessellation.set(
          addExposedField(SFINT32, "uTessellation", new SFInt32(0)));
    vTessellation.set(
          addExposedField(SFINT32, "vTessellation", new SFInt32(0)));

}

Node *
ProtoSuperShape::create(Scene *scene)
{
    return new NodeSuperShape(scene, this); 
}

NodeSuperShape::NodeSuperShape(Scene *scene, Proto *def)
  : MeshBasedNode(scene, def)
{
}

NodeSuperShape::~NodeSuperShape()
{
}

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
NodeSuperShape::createMesh()
{
    if (_mesh)
        delete _mesh;
    _mesh = NULL;
    int           uTess = uTessellation()->getValue();
    int           vTess = vTessellation()->getValue();

    if (uTess <= 0) uTess = 32;
    if (vTess <= 0) vTess = 32;

    uTess++;
    vTess++;

    if (uTess < 3) return;
    if (vTess < 3) return;

    int     size = uTess * vTess;
    Vec3f *vert = new Vec3f[size];
    int* ci = new int[(uTess + 1) * (vTess + 1) * 5];

    float low = -M_PI / 2.0;
    float high = border()->getValue();
    
    float inc1 = M_PI / (uTess-1) * 2.0;
    float inc2 = (high - low) / (vTess-1);
    if (inc2 < EPSILON) return;
    int a1;
    int a2;
    float fua = ua()->getValue();
    float fub = ub()->getValue();
    float fum = um()->getValue();
    float fun1 = un1()->getValue();
    float fun2 = un2()->getValue();
    float fun3 = un3()->getValue();
    Array<float> r1(uTess);
    Array<float> c1(uTess);
    Array<float> s1(uTess);
    for (a1 = 0; a1 < uTess; a1++) {
        float angle1 = -M_PI + a1 * inc1;
        r1[a1] = superFormula(angle1, fua, fub, fum, fun1, fun2, fun3);
        c1[a1] = cos(angle1);
        s1[a1] = sin(angle1);
    }
    float fva = va()->getValue();
    float fvb = vb()->getValue();
    float fvm = vm()->getValue();
    float fvn1 = vn1()->getValue();
    float fvn2 = vn2()->getValue();
    float fvn3 = vn3()->getValue();
    Array<float> r2(vTess);
    Array<float> c2(vTess);
    Array<float> s2(vTess);
    for (a2 = 0; a2 < vTess; a2++) {
        float angle2 = low + a2 * inc2;
        r2[a2] = superFormula(angle2, fva, fvb, fvm, fvn1, fvn2, fvn3);
        c2[a2] = cos(angle2);
        s2[a2] = sin(angle2);
    }
    int index = 0;
    int cindex = 0;
    for (a2 = 0; a2 < vTess; a2++) {
        for (a1 = 0; a1 < uTess; a1++) {
            vert[index].z = r1[a1] * c1[a1] * r2[a2] * c2[a2];
            vert[index].x = r1[a1] * s1[a1] * r2[a2] * c2[a2];
            vert[index].y = r2[a2] * s2[a2];
            index++;
            int c1 = a1 + 1;
            if (a1 == uTess - 1)
               continue;
            int c2 = a2 + 1;
            if (a2 == vTess - 1)
                continue;
            ci[cindex++] = a1 + a2 * uTess;
            ci[cindex++] = c1 + a2 * uTess;
            ci[cindex++] = c1 + c2 * uTess;
            ci[cindex++] = a1 + c2 * uTess;
            ci[cindex++] = -1;
        }
    }

    cindex = cleanDoubleVertices(ci, vert, NULL, cindex);    

    MFVec3f *vertices = new MFVec3f((float *) vert, size * 3);
    MFInt32 *coordIndex = new MFInt32(ci, cindex);
    MFVec2f *texCoords = NULL;
    if (texCoord()->getValue()) {
        if (texCoord()->getValue()->getType() == NODE_TEXTURE_COORDINATE)
          texCoords = ((NodeTextureCoordinate *)(texCoord()->getValue()))
                         ->point();
    } else
      texCoords = generateTextureCoordinates(vertices, coordIndex);

    bool solid = false;
    if (high == M_PI / 2.0)
        solid = true;
    int meshFlags =  MESH_CCW;
    if (solid)
        meshFlags |= MESH_SOLID;

    _mesh = new Mesh(vertices, coordIndex, NULL, NULL,
                     NULL, NULL, texCoords, NULL, creaseAngle()->getValue(), 
                     meshFlags);
}

bool
NodeSuperShape::writeEXTERNPROTO(int f)
{
    RET_ONERROR( mywritestr(f ,"EXTERNPROTO SuperShape[\n") )    
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," exposedField SFFloat ua\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," exposedField SFFloat ub\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," exposedField SFFloat um\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," exposedField SFFloat un1\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," exposedField SFFloat un2\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," exposedField SFFloat un3\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," exposedField SFFloat va\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," exposedField SFFloat vb\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," exposedField SFFloat vm\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," exposedField SFFloat vn1\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," exposedField SFFloat vn2\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," exposedField SFFloat vn3\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 ," field SFNode texCoord\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," exposedField SFInt32 uTessellation\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," exposedField SFInt32 vTessellation\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 ,"SuperShapePROTO.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 ,"SuperShapePROTO.wrl") )
    RET_ONERROR( mywritestr(f ,"\"\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ," \"http://www.csv.ica.uni-stuttgart.de/vrml/dune/docs/scriptedNodes/SuperShapePROTO.wrl\"\n") )
    TheApp->incSelectionLinenumber();
    RET_ONERROR( mywritestr(f ,"]\n") )
    TheApp->incSelectionLinenumber();
    return true;
}

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

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

Node*
NodeSuperShape::toNurbs(int uTess,  int vTess, int uDegree, int vDegree)
{   
    if (_meshDirty) {
        createMesh();
        _meshDirty = false;
    }
    NodeNurbsSurface *node = (NodeNurbsSurface *) _scene->createNode(
                             "NurbsSurface");

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

    int oldUTess = uTessellation()->getValue();
    int oldVTess = vTessellation()->getValue();

    bool storeOldTesselation = false;
    if ((oldUTess != uTess) || (oldVTess != vTess)) {
        storeOldTesselation = true;
        uTessellation(new SFInt32(uTess));
        vTessellation(new SFInt32(vTess));
        createMesh();
        _meshDirty = true;
    }

    uTess++;
    vTess++;

    int size = _mesh->getVertices()->getSize();
    int uDimension = uTess;
    int vDimension = vTess;
    float *controlPoints = new float[size];
    float *weights = new float[size];
    float *uKnots = new float[uDimension + uOrder]; 
    float *vKnots = new float[vDimension + vOrder]; 

    int i;
    for (i = 0; i < size; i++){
        controlPoints[i] = _mesh->getVertices()->getValues()[i];
    }
    for(i = 0; i < size; i++){
        weights[i] = 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);  
    } 
    //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));
    node->ccw(new SFBool(_mesh->ccw()));
    node->solid(new SFBool(_mesh->solid()));

    node->setField(node->uTessellation_Index(), new SFInt32(uTess-1));
    node->setField(node->vTessellation_Index(), new SFInt32(vTess-1));
    for (int iteration = 0; iteration < 2; iteration++) {
        node->reInit();
        node->createMesh();    
        if (node->getVertices() != NULL) {
            assert(size == node->getVertices()->getSize());
            float *vert = new float[size];
            MFVec3f *nurbsControlPoints = node->controlPoint();    
            for (i = 0; i < size; i++) {
                vert[i] = node->getVertices()->getValues()[i];
                float meshValue =_mesh->getVertices()->getValues()[i];
                float nurbsValue = nurbsControlPoints->getValues()[i];
                if (fabs(vert[i]) > EPSILON) {
                    vert[i] = nurbsValue + nurbsValue * meshValue / vert[i];
                    vert[i] = vert[i] / 2.0;
                }
            }
            for (i = 0; i < size; i++) {
                nurbsControlPoints->setValue(i, vert[i]);
            }
        }
    }
    node->setField(node->uTessellation_Index(), new SFInt32(0));
    node->setField(node->vTessellation_Index(), new SFInt32(0));

    if (storeOldTesselation) {
        uTessellation(new SFInt32(oldUTess));
        vTessellation(new SFInt32(oldVTess));
    }

    return node;   
}



Generated by  Doxygen 1.6.0   Back to index