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

NodeTransform.cpp

/*
 * NodeTransform.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 "NodeTransform.h"
#include "Scene.h"
#include "Proto.h"
#include "FieldValue.h"
#include "SFVec3f.h"
#include "SFRotation.h"
#include "SFFloat.h"
#include "MFNode.h"
#include "FieldCommand.h"
#include "Matrix.h"
#include "Util.h"
#include "NodeViewpoint.h"
#include "Field.h"
#include "ExposedField.h"

#define HANDLE_SIZE 1.25f
#define ROTATION_HANDLE_SEGMENTS    40

ProtoTransform::ProtoTransform(Scene *scene)
  : Proto(scene, "Transform")
{
    addEventIn(MFNODE, "addChildren");
    addEventIn(MFNODE, "removeChildren");
    center.set( 
           addExposedField(SFVEC3F, "center", new SFVec3f(0.0f, 0.0f, 0.0f)));
    children.set (
           addExposedField(MFNODE, "children", new MFNode(), CHILD_NODE));
    
    ExposedField* rot = new ExposedField(SFROTATION, "rotation", new 
                                         SFRotation(0.0f, 0.0f, 1.0f, 0.0f));
    rot->setFlags(EIF_RECOMMENDED);
    rotation.set(addExposedField(rot));

    scale.set(
          addExposedField(SFVEC3F, "scale", new SFVec3f(1.0f, 1.0f, 1.0f), 
                      new SFFloat(0.0f)));
    scaleOrientation.set(
          addExposedField(SFROTATION, "scaleOrientation",
                      new SFRotation(0.0f, 0.0f, 1.0f, 0.0f)));
 
    ExposedField* trans = new ExposedField(SFVEC3F, "translation", 
                                           new SFVec3f(0.0f, 0.0f, 0.0f));
    trans->setFlags(EIF_RECOMMENDED);
    translation.set(addExposedField(trans));

    bboxCenter.set(
          addField(SFVEC3F, "bboxCenter", new SFVec3f(0, 0, 0)));
    bboxSize.set(
          addField(SFVEC3F, "bboxSize", new SFVec3f(-1, -1, -1), 
                 new SFFloat(-1.0f)));
}

Node *
ProtoTransform::create(Scene *scene)
{ 
    return new NodeTransform(scene, this); 
}

NodeTransform::NodeTransform(Scene *scene, Proto *def)
  : Node(scene, def)
{
    _matrixDirty = true;
}

NodeTransform::~NodeTransform()
{
}

void
NodeTransform::getMatrix(float* matrix)
{
    for (int i=0;i<16;i++)
       matrix[i]=_matrix[i];
}

const Vec3f &
NodeTransform::getCenter(void)
{
    static Vec3f v;
    v= center()->getValue();
    return v;
}

const Quaternion &
NodeTransform::getQuat(void)
{
    return rotation()->getQuat();
}

const Vec3f &
NodeTransform::getScale(void)
{
    static Vec3f v;
    v = scale()->getValue();
    return v;
}

void 
NodeTransform::setQuat(const Quaternion &quat)
{
    rotation(new SFRotation(quat));
}

void
NodeTransform::transform()
{
    const float   *fcenter = center()->getValue();
    const float   *frotation = rotation()->getValue();
    const float   *fscale = scale()->getValue();
    const float   *fscaleOrientation = scaleOrientation()->getValue();
    const float   *ftranslation = translation()->getValue();

    if (_matrixDirty) {
      glPushMatrix();
      glLoadIdentity();
      glTranslatef(ftranslation[0], ftranslation[1], ftranslation[2]);
      glTranslatef(fcenter[0], fcenter[1], fcenter[2]);
      glRotatef(RAD2DEG(frotation[3]), 
              frotation[0], frotation[1], frotation[2]);
      glRotatef(RAD2DEG(fscaleOrientation[3]), 
              fscaleOrientation[0], fscaleOrientation[1], fscaleOrientation[2]);
      glScalef(fscale[0], fscale[1], fscale[2]);
      glRotatef(-RAD2DEG(fscaleOrientation[3]), 
              fscaleOrientation[0], fscaleOrientation[1], fscaleOrientation[2]);
      glTranslatef(-fcenter[0], -fcenter[1], -fcenter[2]);
      glGetFloatv(GL_MODELVIEW_MATRIX, _matrix);
      glPopMatrix();
      _matrixDirty = false;
    }
    glMultMatrixf((GLfloat *) _matrix);
}

void
NodeTransform::transformForHandle(int handle)
{
    const float   *fcenter = center()->getValue();
    const float   *frotation = rotation()->getValue();
    const float   *fscaleOrientation = scaleOrientation()->getValue();
    const float   *ftranslation = translation()->getValue();

    glTranslatef(ftranslation[0], ftranslation[1], ftranslation[2]);
    glTranslatef(fcenter[0], fcenter[1], fcenter[2]);
    glRotatef(RAD2DEG(frotation[3]), frotation[0], frotation[1], frotation[2]);
    if (handle == SCALE_X || handle == SCALE_Y || handle == SCALE_Z) {
      glRotatef(RAD2DEG(fscaleOrientation[3]), 
              fscaleOrientation[0], fscaleOrientation[1], fscaleOrientation[2]);
    }
    return;
}

void
NodeTransform::draw()
{
    int           i;
    NodeList   *childList = children()->getValues();
    int           n = childList->size();

    glPushMatrix();
    transform();

    for (i = 0; i < n; i++)
      childList->get(i)->bind();

    glPushName(1);                  // field
    glPushName(0);                  // index
    for (i = 0; i < n; i++) {
      glLoadName(i);
      childList->get(i)->draw();
    }
    glPopName();
    glPopName();

    for (i = 0; i < n; i++)
      childList->get(i)->unbind();

    glPopMatrix();
}

void
NodeTransform::drawHandles()
{
    TransformMode* tm=_scene->getTransformMode();
    if (tm->tmode==TM_TRANSLATE)
       drawTranslationHandles();
    else if (tm->tmode==TM_6D)
       draw6DHandles();
    else if (tm->tmode==TM_6DLOCAL)
       draw6DlocalHandles();
    else if (tm->tmode==TM_ROCKET)
       drawRocketHandles();
    else if (tm->tmode==TM_HOVER)
       drawHoverHandles();
    else if (tm->tmode==TM_ROTATE)
       drawRotationHandles();
    else if (tm->tmode==TM_SCALE)
       drawScaleHandles();
    else if (tm->tmode==TM_CENTER)
       drawCenterHandles();
}

void
NodeTransform::drawTranslationHandles()
{
    float    black[4] = { 0.0f, 0.0f, 0.0f, 1.0f };

    glPushMatrix();
    transformForHandle(TRANSLATION);

    glScalef(HANDLE_SIZE, HANDLE_SIZE, HANDLE_SIZE);

    glPushName(TRANSLATION);
    drawAxisLines();

    glEnable(GL_CULL_FACE);

    Util::myGlMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, black);
    Util::myGlMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);

    GLUquadricObj   *obj = gluNewQuadric();

    glLoadName(TRANSLATION_X);
    drawCone(obj, 1.0f, 0.0f, 0.0f);

    glLoadName(TRANSLATION_Y);
    drawCone(obj, 0.0f, 1.0f, 0.0f);

    glLoadName(TRANSLATION_Z);
    drawCone(obj, 0.0f, 0.0f, 1.0f);

    gluDeleteQuadric(obj);
    glPopName();

    glDisable(GL_CULL_FACE);

    glPopMatrix();
}

void
NodeTransform::draw6DHandles()
{
    float    black[4] = { 0.0f, 0.0f, 0.0f, 1.0f };

    glPushMatrix();
    transformForHandle(TRANSLATION);

    glScalef(HANDLE_SIZE, HANDLE_SIZE, HANDLE_SIZE);

    glPushName(TRANSLATION);
    drawAxisLines();

    glEnable(GL_CULL_FACE);

    Util::myGlMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, black);
    Util::myGlMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);

    GLUquadricObj   *obj = gluNewQuadric();

    glLoadName(TRANSLATION_X);
    drawSphere(obj, 1.0f, 0.0f, 0.0f);

    glLoadName(TRANSLATION_Y);
    drawSphere(obj, 0.0f, 1.0f, 0.0f);

    glLoadName(TRANSLATION_Z);
    drawSphere(obj, 0.0f, 0.0f, 1.0f);

    gluDeleteQuadric(obj);
    glPopName();

    glDisable(GL_CULL_FACE);

    glPopMatrix();
}

void
NodeTransform::draw6DlocalHandles()
{
    float    black[4] = { 0.0f, 0.0f, 0.0f, 1.0f };

    glPushMatrix();
    transformForHandle(TRANSLATION);

    glScalef(HANDLE_SIZE, HANDLE_SIZE, HANDLE_SIZE);

    glPushName(TRANSLATION);
    drawAxisLines();

    glEnable(GL_CULL_FACE);

    Util::myGlMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, black);
    Util::myGlMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);

    GLUquadricObj   *obj = gluNewQuadric();

    glLoadName(TRANSLATION_X);
    drawSphere(obj, 1.0f, 0.0f, 0.0f);

    glLoadName(TRANSLATION_Y);
    drawSphere(obj, 0.0f, 1.0f, 0.0f);

    glLoadName(TRANSLATION_Z);
    drawCone(obj, 0.0f, 0.0f, 1.0f);

    gluDeleteQuadric(obj);
    glPopName();

    glDisable(GL_CULL_FACE);

    glPopMatrix();
}

void
NodeTransform::drawRocketHandles()
{
    float    black[4] = { 0.0f, 0.0f, 0.0f, 1.0f };

    glPushMatrix();
    transformForHandle(TRANSLATION);

    glScalef(HANDLE_SIZE, HANDLE_SIZE, HANDLE_SIZE);

    glPushName(TRANSLATION);
    drawAxisLines();

    glEnable(GL_CULL_FACE);

    Util::myGlMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, black);
    Util::myGlMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);

    GLUquadricObj   *obj = gluNewQuadric();

    glLoadName(TRANSLATION_X);
    drawCylinder(obj, 1.0f, 0.0f, 0.0f);

    glLoadName(TRANSLATION_Y);
    drawCylinder(obj, 0.0f, 1.0f, 0.0f);

    glLoadName(TRANSLATION_Z);
    drawCone(obj, 0.0f, 0.0f, 1.0f);

    gluDeleteQuadric(obj);
    glPopName();

    glDisable(GL_CULL_FACE);

    glPopMatrix();
}

void
NodeTransform::drawHoverHandles()
{
    float    black[4] = { 0.0f, 0.0f, 0.0f, 1.0f };

    glPushMatrix();
    transformForHandle(TRANSLATION);

    glScalef(HANDLE_SIZE, HANDLE_SIZE, HANDLE_SIZE);

    glPushName(TRANSLATION);
    drawAxisLines();

    glEnable(GL_CULL_FACE);

    Util::myGlMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, black);
    Util::myGlMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);

    GLUquadricObj   *obj = gluNewQuadric();

    glLoadName(TRANSLATION_X);
    drawAntiCone(obj, 1.0f, 0.0f, 0.0f);

    glLoadName(TRANSLATION_Y);
    drawAntiCone(obj, 0.0f, 1.0f, 0.0f);

    glLoadName(TRANSLATION_Z);
    drawCone(obj, 0.0f, 0.0f, 1.0f);

    gluDeleteQuadric(obj);
    glPopName();

    glDisable(GL_CULL_FACE);

    glPopMatrix();
}

void
NodeTransform::drawScaleHandle(float x, float y, float z)
{
    float   color[4] = {x, y, z, 1.0f};

    Util::myGlMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color);

    glPushMatrix();
    glRotatef(90.0f * x - 90.0f * y, y, x, z);
    glTranslatef(0.0f, 0.0f, 1.1f);
    Util::DrawBox(0.1f, 0.1f, 0.1f);
    glPopMatrix();
}

void
NodeTransform::drawCenterHandles()
{
    float    black[4] = { 0.0f, 0.0f, 0.0f, 1.0f };

    glPushMatrix();
    transformForHandle(CENTER);

    glScalef(HANDLE_SIZE, HANDLE_SIZE, HANDLE_SIZE);

    glPushName(CENTER);
    drawAxisLines();

    glEnable(GL_CULL_FACE);

    Util::myGlMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, black);
    Util::myGlMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);

    GLUquadricObj   *obj = gluNewQuadric();

    glLoadName(CENTER_X);
    drawCone(obj, 1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f);

    glLoadName(CENTER_Y);
    drawCone(obj, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f, 0.0f);

    glLoadName(CENTER_Z);
    drawCone(obj, 0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f);

    gluDeleteQuadric(obj);
    glPopName();

    glDisable(GL_CULL_FACE);

    glPopMatrix();
}

void
NodeTransform::drawCone(GLUquadricObj *obj, float x, float y, float z)
{
    drawCone(obj,x,y,z, x,y,z);
}

void
NodeTransform::drawCone(GLUquadricObj *obj, float x, float y, float z,
                                            float r, float b, float g)
{
    float   color[4] = {r, b, g, 1.0f};

    Util::myGlMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color);

    glPushMatrix();
    glRotatef(90.0f * x - 90.0f * y, y, x, z);
    glTranslatef(0.0f, 0.0f, 1.0f);
    gluCylinder(obj, 0.07, 0.0, 0.2, 10, 10);
    gluQuadricOrientation(obj, (GLenum) GLU_INSIDE);
    gluDisk(obj, 0.0, 0.07, 10, 1);
    gluQuadricOrientation(obj, (GLenum) GLU_OUTSIDE);
    glPopMatrix();
}

void
NodeTransform::drawSphere(GLUquadricObj *obj, float x, float y, float z)
{
    drawSphere(obj,x,y,z, x,y,z);
}

void
NodeTransform::drawSphere(GLUquadricObj *obj, float x, float y, float z,
                                              float r, float b, float g)
{
    float   color[4] = {r, b, g, 1.0f};

    Util::myGlMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color);

    glPushMatrix();
    glRotatef(90.0f * x - 90.0f * y, y, x, z);
    glTranslatef(0.0f, 0.0f, 1.0f);
    gluSphere(obj, 0.07, 10, 10);
    glPopMatrix();
}

void
NodeTransform::drawAntiCone(GLUquadricObj *obj, float x, float y, float z)
{
    drawAntiCone(obj,x,y,z, x,y,z);
}

void
NodeTransform::drawAntiCone(GLUquadricObj *obj, float x, float y, float z,
                                                float r, float b, float g)
{
    float   color[4] = {r, b, g, 1.0f};

    Util::myGlMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color);

    glPushMatrix();
    glRotatef(90.0f * x - 90.0f * y, y, x, z);
    glTranslatef(0.0f, 0.0f, 1.0f);
    gluCylinder(obj, 0.0, 0.07, 0.2, 10, 10);
    glTranslatef(0.0f, 0.0f, 0.2f);
    gluDisk(obj, 0.0, 0.07, 10, 1);
    glPopMatrix();
}

void
NodeTransform::drawCylinder(GLUquadricObj *obj, float x, float y, float z)
{
    drawCylinder(obj,x,y,z, x,y,z);
}

void
NodeTransform::drawCylinder(GLUquadricObj *obj, float x, float y, float z,
                                                float r, float b, float g)
{
    float   color[4] = {r, b, g, 1.0f};

    Util::myGlMaterialfv(GL_FRONT_AND_BACK, GL_DIFFUSE, color);

    glPushMatrix();
    glRotatef(90.0f * x - 90.0f * y, y, x, z);
    glTranslatef(0.0f, 0.0f, 1.0f);
    gluCylinder(obj, 0.07, 0.07, 0.2, 10, 10);
    gluQuadricOrientation(obj, (GLenum) GLU_INSIDE);
    gluDisk(obj, 0.0, 0.07, 10, 1);
    gluQuadricOrientation(obj, (GLenum) GLU_OUTSIDE);
    glTranslatef(0.0f, 0.0f, 0.2f);
    gluDisk(obj, 0.0, 0.07, 10, 1);
    glPopMatrix();
}

void
NodeTransform::preDraw()
{
    NodeList    *childList = children()->getValues();

    glPushMatrix();
    transform();

    for (int i = 0; i < childList->size(); i++)
      childList->get(i)->preDraw();

    glPopMatrix();
}

void
NodeTransform::drawRotationHandles()
{
    float   inc = 2 * PI / ROTATION_HANDLE_SEGMENTS;
    float   i;
    GLint   mode;

    glGetIntegerv(GL_RENDER_MODE, &mode);
    bool    picking = mode == GL_SELECT;

    glPushMatrix();
    glPushAttrib(GL_LIGHTING | GL_LINE_SMOOTH | GL_BLEND);
    glDisable(GL_LIGHTING);
    glEnable(GL_LINE_SMOOTH);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);

    glPushName(ROTATION);
    transformForHandle(ROTATION);
    if (picking) {
      float     mat[4][4];
      glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *) mat);
      glPushMatrix();
      glLoadIdentity();
      glTranslatef(mat[3][0], mat[3][1], mat[3][2]);
      glScalef(HANDLE_SIZE, HANDLE_SIZE, HANDLE_SIZE);
      Util::myGlColor4f(1.0f, 1.0f, 1.0f, 0.5f);
      glBegin(GL_POLYGON);

      for (i = 0.0f; i < 2 * PI; i += inc) {
          float       s = (float) sin(i);
          float       c = (float) cos(i);
          glVertex3f(c, s, 0.0f);
      }
      glEnd();
      glPopMatrix();
    }

    glScalef(HANDLE_SIZE, HANDLE_SIZE, HANDLE_SIZE);

    glLoadName(ROTATION_X);
    Util::myGlColor3f(1.0f, 0.0f, 0.0f);
    glBegin(GL_LINE_LOOP);

    for (i = 0.0f; i < 2 * PI; i += inc) {
      float     s = (float) sin(i);
      float     c = (float) cos(i);
      glVertex3f(0.0f, c, s);
    }
    glEnd();

    glLoadName(ROTATION_Y);
    Util::myGlColor3f(0.0f, 1.0f, 0.0f);
    glBegin(GL_LINE_LOOP);

    for (i = 0.0f; i < 2 * PI; i += inc) {
      float     s = (float) sin(i);
      float     c = (float) cos(i);
      glVertex3f(s, 0.0f, c);
    }
    glEnd();

    glLoadName(ROTATION_Z);
    Util::myGlColor3f(0.0f, 0.0f, 1.0f);
    glBegin(GL_LINE_LOOP);

    for (i = 0.0f; i < 2 * PI; i += inc) {
      float     s = (float) sin(i);
      float     c = (float) cos(i);
      glVertex3f(c, s, 0.0f);
    }
    glEnd();

    glPopMatrix();
    glPopName();
    glPopAttrib();
}

void
NodeTransform::drawAxisLines()
{
    float    white[4] = { 1.0f, 1.0f, 1.0f, 1.0f };

    glPushAttrib(GL_LIGHTING | GL_LINE_SMOOTH | GL_BLEND);
    glDisable(GL_LIGHTING);
    glEnable(GL_LINE_SMOOTH);
    glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
    glEnable(GL_BLEND);

    Util::myGlColor3fv(white);
    glBegin(GL_LINES);
    glVertex3i(0, 0, 0);
    glVertex3i(1, 0, 0);
    glVertex3i(0, 0, 0);
    glVertex3i(0, 1, 0);
    glVertex3i(0, 0, 0);
    glVertex3i(0, 0, 1);
    glEnd();

    glDisable(GL_CULL_FACE);
    glPopAttrib();
}

void
NodeTransform::drawScaleHandles()
{
    float    black[4] = { 0.0f, 0.0f, 0.0f, 1.0f };

    glPushMatrix();
    transformForHandle(SCALE_X);
    const float   *fscale = scale()->getValue();
    glScalef(fscale[0], fscale[1], fscale[2]);

    glScalef(HANDLE_SIZE, HANDLE_SIZE, HANDLE_SIZE);

    glPushName(TRANSLATION);
    drawAxisLines();

    glEnable(GL_CULL_FACE);

    Util::myGlMaterialfv(GL_FRONT_AND_BACK, GL_EMISSION, black);
    Util::myGlMaterialfv(GL_FRONT_AND_BACK, GL_SPECULAR, black);

    glLoadName(SCALE_X);
    drawScaleHandle(1.0f, 0.0f, 0.0f);

    glLoadName(SCALE_Y);
    drawScaleHandle(0.0f, 1.0f, 0.0f);

    glLoadName(SCALE_Z);
    drawScaleHandle(0.0f, 0.0f, 1.0f);

    glPopName();

    glDisable(GL_CULL_FACE);

    glPopMatrix();
}

Vec3f
NodeTransform::getHandle(int handle, int *constraint, int *field)
{
    const float   *fscale = scale()->getValue();
    SFRotation *sfrotation = rotation();

    switch (handle) {
      case TRANSLATION_X:
      *constraint = CONSTRAIN_X;
      *field = 5;
      return Vec3f(HANDLE_SIZE, 0.0f, 0.0f);
      case TRANSLATION_Y:
      *constraint = CONSTRAIN_Y;
      *field = 5;
      return Vec3f(0.0f, HANDLE_SIZE, 0.0f);
      case TRANSLATION_Z:
      *constraint = CONSTRAIN_Z;
      *field = 5;
      return Vec3f(0.0f, 0.0f, HANDLE_SIZE);
      case TRANSLATION:
      *field = 5;
      return Vec3f(0.0f, 0.0f, 0.0f);
      case ROTATION:
      *field = 2;
      *constraint = CONSTRAIN_SPHERE;
      return sfrotation->getEulerAngles(0);
      case ROTATION_X:
      *field = 2;
      *constraint = CONSTRAIN_YZ;
      return Vec3f(0.0f, 0.0f, 0.0f);
      case ROTATION_Y:
      *field = 2;
      *constraint = CONSTRAIN_ZX;
      return Vec3f(0.0f, 0.0f, 0.0f);
      case ROTATION_Z:
      *field = 2;
      *constraint = CONSTRAIN_XY;
      return Vec3f(0.0f, 0.0f, 0.0f);
      case SCALE_X:
      *constraint = CONSTRAIN_X;
      *field = 3;
      return Vec3f(fscale[0] * HANDLE_SIZE, 0.0f, 0.0f);
      case SCALE_Y:
      *constraint = CONSTRAIN_Y;
      *field = 3;
      return Vec3f(0.0f, fscale[1] * HANDLE_SIZE, 0.0f);
      case SCALE_Z:
      *constraint = CONSTRAIN_Z;
      *field = 3;
      return Vec3f(0.0f, 0.0f, fscale[2] * HANDLE_SIZE);
      case CENTER_X:
      *constraint = CONSTRAIN_X;
      *field = 0;
      return Vec3f(HANDLE_SIZE, 0.0f, 0.0f);
      case CENTER_Y:
      *constraint = CONSTRAIN_Y;
      *field = 0;
      return Vec3f(0.0f, HANDLE_SIZE, 0.0f);
      case CENTER_Z:
      *constraint = CONSTRAIN_Z;
      *field = 0;
      return Vec3f(0.0f, 0.0f, HANDLE_SIZE);
      case CENTER:
      *field = 0;
      return Vec3f(0.0f, 0.0f, 0.0f);
      default:
      assert(0);
        *field = 3;
      return Vec3f(fscale);
    }
}

void
NodeTransform::setHandle(int handle, const Vec3f &v)
{
    const float   *fcenter = center()->getValue();
    SFRotation  *sfrotation = rotation();
    const float   *rot = sfrotation->getValue();
    const float   *fscale = scale()->getValue();
    const float   *ftranslation = translation()->getValue();
    Matrix   mat;

    glPushMatrix();
    glLoadIdentity();
    if ((handle==CENTER_X) || (handle==CENTER_Y) || (handle==CENTER_Z) ||
        (handle==CENTER))
       glTranslatef(fcenter[0], fcenter[1], fcenter[2]);
    else
       glTranslatef(ftranslation[0], ftranslation[1], ftranslation[2]);
    glRotatef(RAD2DEG(rot[3]), rot[0], rot[1], rot[2]);
    glGetFloatv(GL_MODELVIEW_MATRIX, mat);
    glPopMatrix();

    ProtoTransform *proto = (ProtoTransform *)getProto();

    switch (handle) {
      case TRANSLATION:
      _scene->setField(this, proto->translation, new SFVec3f(mat * v));
      break;
      case TRANSLATION_X:
      _scene->setField(this, proto->translation, 
              new SFVec3f(mat * (v - Vec3f(HANDLE_SIZE, 0.0f, 0.0f))));
      break;
      case TRANSLATION_Y:
      _scene->setField(this, proto->translation, 
              new SFVec3f(mat * (v - Vec3f(0.0f, HANDLE_SIZE, 0.0f))));
      break;
      case TRANSLATION_Z:
      _scene->setField(this, proto->translation, 
              new SFVec3f(mat * (v - Vec3f(0.0f, 0.0f, HANDLE_SIZE))));
      break;
      case ROTATION:
      _scene->setField(this, proto->rotation, new SFRotation(v, 0));
      break;
      case ROTATION_X:
      _scene->setField(this, proto->rotation, 
              new SFRotation(Quaternion(Vec3f(1.0f, 0.0f, 0.0f), v.x) * 
                             sfrotation->getQuat()));
      break;
      case ROTATION_Y:
      _scene->setField(this, proto->rotation, 
              new SFRotation(Quaternion(Vec3f(0.0f, 1.0f, 0.0f), v.y) * 
                             sfrotation->getQuat()));
      break;
      case ROTATION_Z:
      _scene->setField(this, proto->rotation, 
              new SFRotation(Quaternion(Vec3f(0.0f, 0.0f, 1.0f), v.z) * 
                             sfrotation->getQuat()));
      break;
      case SCALE_X:
      if (v.x > 0.0f) {
          _scene->setField(this, proto->scale, 
                             new SFVec3f(Vec3f(v.x, fscale[1], fscale[2])));
      }
      break;
      case SCALE_Y:
      if (v.y > 0.0f) {
          _scene->setField(this, proto->scale, 
                             new SFVec3f(Vec3f(fscale[0], v.y, fscale[2])));
      }
      break;
      case SCALE_Z:
      if (v.z > 0.0f) {
          _scene->setField(this, proto->scale, 
                             new SFVec3f(Vec3f(fscale[0], fscale[1], v.z)));
      }
      break;
      case SCALE:
      if ((v.x > 0.0f) && (v.y > 0.0f) && (v.z > 0.0f)) {
          _scene->setField(this, proto->scale, 
                             new SFVec3f(Vec3f(v.x,v.y,v.z)));
      }
      break;
      case CENTER:
      _scene->setField(this, proto->center, new SFVec3f(mat * v));
      break;
      case CENTER_X:
      _scene->setField(this, proto->center, 
              new SFVec3f(mat * (v - Vec3f(HANDLE_SIZE, 0.0f, 0.0f))));
      break;
      case CENTER_Y:
      _scene->setField(this, proto->center, 
              new SFVec3f(mat * (v - Vec3f(0.0f, HANDLE_SIZE, 0.0f))));
      break;
      case CENTER_Z:
      _scene->setField(this, proto->center, 
              new SFVec3f(mat * (v - Vec3f(0.0f, 0.0f, HANDLE_SIZE))));
      break;
      default:
      assert(0);
      break;
    }
}

void
NodeTransform::receiveEvent(int eventIn, double timestamp, FieldValue *value)
{
    switch (eventIn) {
    case 0:
      // FIXME:  do addChildren here
      break;
    case 1:
      // FIXME:  do removeChildren here
      break;
    default:
      Node::receiveEvent(eventIn, timestamp, value);
      break;
    }
}

void
NodeTransform::setField(int field, FieldValue *value)
{
    if (field != 1) _matrixDirty = true;
    Node::setField(field, value);
}

void
NodeTransform::flip(int index)
{
    center()->flip(index);
    rotation()->flip(index);
    scaleOrientation()->flip(index);
    translation()->flip(index);
    bboxCenter()->flip(index);

    NodeList    *childList = children()->getValues();

    for (int i = 0; i < childList->size(); i++)
      childList->get(i)->flip(index);
    _matrixDirty = true;
}

int         
NodeTransform::countPolygons(void)
{
    int ret = 0;
    NodeList    *childList = children()->getValues();

    for (int i = 0; i < childList->size(); i++)
        ret += childList->get(i)->countPolygons();

    return ret;
}

int         
NodeTransform::countPrimitives(void)
{
    int ret = 0;
    NodeList    *childList = children()->getValues();

    for (int i = 0; i < childList->size(); i++)
        ret += childList->get(i)->countPrimitives();

    return ret;
}


Generated by  Doxygen 1.6.0   Back to index