VISH  0.2
Gear.cpp

An example of a rotating gear, as derived from an Qt example.

#include <stdio.h>

#include <ocean/GLvish/VGLRenderObject.hpp>
#include <ocean/GLvish/Pickable.hpp>
#include <ocean/plankton/VCreator.hpp>
#include <ocean/plankton/VTime.hpp>
#include <ocean/GLvish/BoundingBox.hpp>

#include <stdio.h>

using namespace Wizt;

namespace
{

class   GearExample : public Wizt::VGLRenderObject, public Pickable
{
        struct  AccelState : State
        {
                double  last_t;
                float   phi0, phi1, phi2;
                float current_speed,
                      target_speed;
        };

        virtual void render(VGLRenderContext&Context) const;
public:

        TypedSlot<int>  Teeth,  
                        Speed;  


        GearExample(const string&name, int p, const RefPtr<VCreationPreferences>&VP)
        : VGLRenderObject(name, p, VP)
        , Teeth(this, "teeth", 10)
        , Speed(this, "speed", 10)
        {
                // Define speed as a parameter local to each viewer context 
                Speed->Localize();

                // Explicit setting of a bounding box to this object
        //      myBBox() = new BoundingBox(point(-1,-1,-1), point(1,1,1) );
        }

        ~GearExample()
        {}

        override bool request(VRequest&R, double precision,
                              const WeakVObjectPtr&ImmediateRequestor, 
                              const WeakVObjectPtr&RootRequestor)

        {
                age(R).touch(); 
                return VGLRenderObject::request(R,precision, ImmediateRequestor, RootRequestor);
        }

        void GearRender(VGLRenderContext&Context, const GLfloat red[4]) const;
};

/*
 * Draw a gear wheel.  You'll probably want to call this function when
 * building a display list since we do a lot of trig here.

 --> should do this via display lists and transformation matrix!

 *
 * Input:  inner_radius - radius of hole at center
 *         outer_radius - radius at center of teeth
 *         width - width of gear
 *         teeth - number of teeth
 *         tooth_depth - depth of tooth
 */
static void gear( GLfloat inner_radius, GLfloat outer_radius, GLfloat width,
                  GLint teeth, GLfloat tooth_depth, float offset )
{
GLint   i; 
GLfloat r0, r1, r2; 
GLfloat angle, da; 
GLfloat u, v, len; 

        r0 = inner_radius; 
        r1 = outer_radius - tooth_depth/2.0; 
        r2 = outer_radius + tooth_depth/2.0; 

const double pi = 3.14159264; 
        da = 2.0*pi / teeth / 4.0; 
        glShadeModel( GL_SMOOTH ); 

        glNormal3f( 0.0, 0.0, 1.0 ); 

        /* draw front face */
        glBegin( GL_QUAD_STRIP ); 
        for (i=0;i<=teeth;i++)
        {
                angle = i * 2.0*pi / teeth + offset; 
                glVertex3f( r0*cos(angle), r0*sin(angle), width*0.5 ); 
                glVertex3f( r1*cos(angle), r1*sin(angle), width*0.5 ); 
                glVertex3f( r0*cos(angle), r0*sin(angle), width*0.5 ); 
                glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5 );
        } 
        glEnd(); 

        /* draw front sides of teeth */ 
        glBegin( GL_QUADS ); 
        da = 2.0*pi / teeth / 4.0; 
        for (i=0;i<teeth;i++) 
        {
                angle = i * 2.0*pi / teeth + offset; 

                glVertex3f( r1*cos(angle),      r1*sin(angle),    width*0.5 ); 
                glVertex3f( r2*cos(angle+da),   r2*sin(angle+da),         width*0.5 ); 
                glVertex3f( r2*cos(angle+2*da), r2*sin(angle+2*da), width*0.5 ); 
                glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), width*0.5 );
        } 
        glEnd(); 

        glNormal3f( 0.0, 0.0, -1.0 ); 

        /* draw back face */ 
        glBegin( GL_QUAD_STRIP ); 
        for (i=0;i<=teeth;i++) 
        {
                angle = i * 2.0*pi / teeth + offset; 
                glVertex3f( r1*cos(angle), r1*sin(angle), -width*0.5 ); 
                glVertex3f( r0*cos(angle), r0*sin(angle), -width*0.5 ); 
                glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5 ); 
                glVertex3f( r0*cos(angle), r0*sin(angle), -width*0.5 );
        } 
        glEnd(); 

        /* draw back sides of teeth */ 
        glBegin( GL_QUADS ); 
        da = 2.0*pi / teeth / 4.0; 
        for (i=0;i<teeth;i++)
        {
                angle = i * 2.0*pi / teeth + offset; 

                glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5 ); 
                glVertex3f( r2*cos(angle+2*da), r2*sin(angle+2*da), -width*0.5 ); 
                glVertex3f( r2*cos(angle+da),   r2*sin(angle+da),         -width*0.5 ); 
                glVertex3f( r1*cos(angle),      r1*sin(angle),    -width*0.5 );
        } 
        glEnd(); 


        /* draw outward faces of teeth */ 
        glBegin( GL_QUAD_STRIP ); 
        for (i=0;i<teeth;i++) 
        {
                angle = i * 2.0*pi / teeth + offset; 

                glVertex3f( r1*cos(angle),      r1*sin(angle),     width*0.5 ); 
                glVertex3f( r1*cos(angle),      r1*sin(angle),    -width*0.5 ); 
                u = r2*cos(angle+da) - r1*cos(angle); 
                v = r2*sin(angle+da) - r1*sin(angle); 
                len = sqrt( u*u + v*v ); 
                u /= len; 
                v /= len; 
                glNormal3f( v, -u, 0.0 ); 
                glVertex3f( r2*cos(angle+da),   r2*sin(angle+da),          width*0.5 ); 
                glVertex3f( r2*cos(angle+da),   r2*sin(angle+da),         -width*0.5 ); 
                glNormal3f( cos(angle), sin(angle), 0.0 ); 
                glVertex3f( r2*cos(angle+2*da), r2*sin(angle+2*da),  width*0.5 ); 
                glVertex3f( r2*cos(angle+2*da), r2*sin(angle+2*da), -width*0.5 ); 
                u = r1*cos(angle+3*da) - r2*cos(angle+2*da); 
                v = r1*sin(angle+3*da) - r2*sin(angle+2*da); 
                glNormal3f( v, -u, 0.0 ); 
                glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da),  width*0.5 ); 
                glVertex3f( r1*cos(angle+3*da), r1*sin(angle+3*da), -width*0.5 ); 
                glNormal3f( cos(angle), sin(angle), 0.0 );
        } 

        glVertex3f( r1*cos(offset), r1*sin(offset), width*0.5 ); 
        glVertex3f( r1*cos(offset), r1*sin(offset), -width*0.5 ); 

        glEnd(); 

        glShadeModel( GL_SMOOTH ); 

        /* draw inside radius cylinder */ 
        glBegin( GL_QUAD_STRIP ); 
        for (i=0;i<=teeth;i++)
        {
                angle = i * 2.0*pi / teeth + offset; 
                glNormal3f( -cos(angle), -sin(angle), 0.0 ); 
                glVertex3f( r0*cos(angle), r0*sin(angle), -width*0.5 ); 
                glVertex3f( r0*cos(angle), r0*sin(angle), width*0.5 );
        } 
        glEnd();
}


void GearExample::render(VGLRenderContext&Context) const
{
//static        GLfloat pos[4]   = {5.0, 5.0, 10.0, 1.0 }; 
static  GLfloat red[4]   = {0.1, 0.1, 0.1, 1.0 }; 
//static        GLfloat green[4] = {0.0, 0.8, 0.2, 1.0 }; 
//static        GLfloat blue[4]  = {0.2, 0.2, 1.0, 1.0 }; 
//static        GLfloat white[4] = {0.8, 0.8, 0.9, 1.0 }; 

        resetBBox(Context);
        GearRender(Context, red); 
        closeBBox(Context);
}

void GearExample::GearRender(VGLRenderContext&Context, const GLfloat red[4]) const
{
//static        GLfloat pos[4]   = {5.0, 5.0, 10.0, 1.0 }; 
static  GLfloat Red[4]   = {0.9, 0.1, 0.1, 1.0 }; 
static  GLfloat green[4] = {0.0, 0.8, 0.2, 1.0 }; 
static  GLfloat blue[4]  = {0.2, 0.2, 1.0, 1.0 }; 
//static        GLfloat white[4] = {0.8, 0.8, 0.9, 1.0 }; 

//puts("void GearExample::GearRender(VGLRenderContext&Context, const GLfloat red[4]) "); 

//fprintf(stderr,"void GearExample::GearRender(VGLRenderContext&Context, const GLfloat red[4]) "); fflush(stderr); 

//      glPushAttrib(GL_ALL_ATTRIB_BITS); 

//      glDisable(GL_CULL_FACE ); 
        glEnable(GL_CULL_FACE ); 
        glEnable( GL_LIGHTING ); 
//      glEnable( GL_LIGHT0 ); 
        glEnable( GL_DEPTH_TEST );      

        glEnable( GL_COLOR_MATERIAL );
        glColorMaterial( GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE );

int     speed = 100; 

        /*
          This is the operator interface to retrieve values from a slot!
         */
        Speed << Context >> speed; 

RefPtr<AccelState> myState = getState(Context);
        if (!myState)
        {
                myState = new AccelState();
                setState(Context, myState);
                myState->target_speed = myState->current_speed = speed;

                myState->phi0 = myState->phi1 = myState->phi2 = 0;
                myState->last_t = Context.time.seconds;
        }
        else
                myState->target_speed = speed;

        if (myState->current_speed < myState->target_speed)
                myState->current_speed+=2;

        if (myState->current_speed > myState->target_speed)
                myState->current_speed-=2;

float   omega = myState->current_speed / 50.0;
double  t = Context.time.seconds,
        dt = t - myState->last_t;
        myState->last_t = t;
        //printf("time: %20.20lg %lg %20.20lg\n", t, dt, myState->last_t);

        myState->phi0 +=      omega*dt;
        myState->phi1 += -2.0*omega*dt;
        myState->phi2 +=0.566*omega*dt;

int     teeth = 10;
        Teeth << Context >> teeth; 

        embrace( Context, point(-3,-2,0) + tvector3(4.0, 4.0, 1.1) );
        embrace( Context, point(-3,-2,0) - tvector3(4.0, 4.0, 1.1) );

        SubObjectBegin(Context);
        glPushMatrix();
        glTranslatef( -3.0, -2.0, 0.0 );
        vglColor4fv(Context, Red, 0.4); 
        glColor4fv(Red);
        gear( 1.0, 4.0, 1.0, 17+teeth, 1.1, myState->phi0);
        glPopMatrix();

        embrace( Context, point(3.1,-2,0) + tvector3(2.0, 2.0, 0.7) );
        embrace( Context, point(3.1,-2,0) - tvector3(2.0, 2.0, 0.7) );

        SubObjectBegin(Context);
        glPushMatrix();
        glTranslatef( 3.1, -2.0, 0.0 );
        vglColor4fv(Context, green, 0.4); 
        gear( 0.5, 2.0, 2.0, 10+teeth, 0.7, myState->phi1); 
        glPopMatrix();

        embrace( Context, point(-3.1, 2.2,-5.8) + tvector3(6.0, 1.2, 6.0) );
        embrace( Context, point(-3.1, 2.2,-5.8) - tvector3(6.0, 1.2, 6.0) );

        SubObjectBegin(Context);
        glPushMatrix();
        glTranslatef( -3.1, 2.2, -5.8 );
        glRotatef( 90.0, 1.0, 0.0, 0.0 );
        vglColor4fv(Context, blue, 0.4); 
        gear( 1.3, 6.0, 0.3, 30+teeth, 1.2, myState->phi2);
        glPopMatrix();

        closeBBox( Context );
}


static Ref<VCreator<GearExample> > gearCreator("Gear", ObjectQuality::DEMO);
//static VGlobalCreator<GearExample> gearCreator("Gear", 0);

class   DynamicGear : public GearExample
{
public:
        TypedSlot<VTime>        myTime;

        DynamicGear (const string&name, int p, const RefPtr<VCreationPreferences>&VP)
        : GearExample(name, p, VP)
        , myTime(this, "time", VTime(0.0) )
        {
        }

        void render(VGLRenderContext&Context) const
        {
        VTime   t; 
                myTime << Context >> t; 
                printf("time t[%lg] \n", t() );


        GLfloat red[4]   = {0.1, 0.1, 0.1, 1.0 }; 

                red[0] = 1-t();
                red[2] = t();
                GearRender(Context, red);
        }
};

static Ref<VCreator<DynamicGear> > DynamicGearCreator("Demo/DynamicGear", ObjectQuality::DEMO);

}

VISH_DEFAULT_INIT