Source Code for Project Solid


The following source file, led by a gray banner, contains all the class functions needed for Project Solid.  The sections highlighted by a yellow background Color are manually entered.  Code sections with white background color are generated by the SansGUI Source Code Framework.  The source file is compiled into a dynamic linked library to be invoked by SansGUI during simulation runs.

For more details about this example, please read the Solid On-Line Manual.

Implementation in C/C++ (MSVC)

Functions in Class Graphics.Solid    [Go To Top]

/* Graphics_Solid.c
 * - DLL routines for class <Reference>Graphics.Solid
 * DATE: Thursday, February 20, 2003 TIME: 02:04:29 PM
 * The skeleton of this file is generated by SansGUI(tm)
 */

#include <stdio.h>

#include <windows.h> /* required by gl.h */
#include <gl/gl.h>
#include <gl/glu.h>
#include <gl/glaux.h>

#include "SGdll.h"

#ifdef __cplusplus
extern "C"
{
#endif

SG_EXPORT SG_SIM_FUNC SG_xBgnRun_Graphics_Solid;
SG_EXPORT SG_SIM_FUNC SG_xPreEval_Graphics_Solid;
SG_EXPORT SG_SIM_FUNC SG_xEval_Graphics_Solid;
SG_EXPORT SG_SIM_FUNC SG_xPostEval_Graphics_Solid;

#ifdef __cplusplus
}
#endif

/* Macros for attribute indices in class version [1.0.alpha.5] */
#define SG_NDX_ITRACKER 0 /* iTracker - Selection Tracker */
#define SG_NDX_ISELECT 1 /* iSelect - Selection Area [x1 y1 x2 y2] */
#define SG_NDX_IWINSIZE 2 /* iWinSize - Window Size [x y] */
#define SG_NDX_FSCALE 3 /* fScale - Scaling Factors [x y z] */
#define SG_NDX_FROTATE 4 /* fRotate - Rotation Angles [x y z] */
#define SG_NDX_FTRANSLATE 5 /* fTranslate - Translation Vector [x y z] */
#define SG_NDX_IFLAGS 6 /* iFlags - Control Flags (Reserved) */
#define SG_NDX_SEXTFILE 7 /* sExtFile - External File (Reserved) */
#define SG_NDX_ISHAPE 8 /* iShape - 3D Object Shape */
#define SG_NDX_ICOLOR 9 /* iColor - Color of Object */
#define SG_NDX_ITYPE 10 /* iType - Display Method */
#define SG_NDX_FANGLE 11 /* fAngle - Current Angle */

static GLfloat s_vfAmbientLight[] = { 0.2f, 0.2f, 0.2f, 1.0f };
static GLfloat s_vfDiffuseLight[] = { 0.6f, 0.6f, 0.6f, 1.0f };
static GLfloat s_vfSpecular[] = { 1.0f, 0.5f, 0.5f, 1.0f };
static GLfloat s_vfLightPos[] = { 1.0f, 2.0f, 0.0f, 1.0f };

enum
{
    TRACK_NONE = 0, TRACK_POINT = 1, TRACK_LINE = 2, TRACK_RECT = 3
};

enum
{
    COLOR_CYAN = 0, COLOR_MAGENTA = 1, COLOR_YELLOW = 2
};

enum
{
    SHAPE_TETRAHEDRON = 0, SHAPE_CUBE = 1, SHAPE_OCTAHEDRON = 2,
    SHAPE_DODECAHEDRON = 3, SHAPE_ICOSAHEDRON = 4, SHAPE_BOX = 5,
    SHAPE_CYLINDER = 6, SHAPE_CONE = 7, SHAPE_SPHERE = 8,
    SHAPE_TORUS = 9, SHAPE_TEAPOT = 10
};

/* ============================================================
 * SG_xBgnRun - Begin Run
 * ------------------------------------------------------------
 */
SG_RET_CODE SG_xBgnRun_Graphics_Solid(SG_OBJ *const self,
          SG_OBJ *const simCtrl, SG_OBJ *const chgChild,
          SG_OBJ *const refObjs[], const INT *const piRefObjs,
          SG_OBJ *const adjObjs[], const INT *const piAdjObjs,
          SG_OBJ *const lnkObjs[], const INT *const piLnkObjs,
          TCHAR *const cMessage, const INT iMsgLen,
          TCHAR *const cCommand, const INT iCmdLen,
          SG_FILE *const pOutFile )
{
    /* TODO: declare your local variables here */

    INT *iTrack = &self->zValues[SG_NDX_ITRACKER].iData[0];

    if (!SG_IsSchemaOK(self->nSGobjSchema))
        return SG_R_SCHM;

    /* TODO: put your simulator code here */

    /* NOTE: When the SG_STAT_EDIT bit is set, this routine is called by the
     * SansGUI Framework in the case that the rendering context of the
     * OpenGL(R) window needs to be set up. If the bit is not set,
     * this routine is called during a simulation run with the regular
     * SansGUI DLL function call semantics.
     */
    if (SG_IsEditing(self->iStatus))
    {   /* when the OpenGL rendering context needs to be set up */
        *iTrack = TRACK_RECT; /* set selection tracker type */

        glEnable(GL_DEPTH_TEST); /* hidden surface removal */
        glEnable(GL_COLOR_MATERIAL);

        if (SG_IsPrinting(self->iStatus)) /* print to printer */
            glClearColor(1.0f, 1.0f, 1.0f, 1.0f); /* white background */
        else
            glClearColor(0.0f, 0.0f, 0.7f, 1.0f); /* dark blue background */

        glEnable(GL_LIGHTING);
        glLightfv(GL_LIGHT0, GL_AMBIENT, s_vfAmbientLight);
        glLightfv(GL_LIGHT0, GL_DIFFUSE, s_vfDiffuseLight);
        glLightfv(GL_LIGHT0, GL_SPECULAR, s_vfSpecular);
        glLightfv(GL_LIGHT0, GL_POSITION, s_vfLightPos);
        glEnable(GL_LIGHT0);

        glColorMaterial(GL_FRONT, GL_AMBIENT_AND_DIFFUSE);
        glMaterialfv(GL_FRONT, GL_SPECULAR, s_vfSpecular);
        glMateriali(GL_FRONT, GL_SHININESS, 100);
    }

    return SG_R_OK;
}

/* ============================================================
* SG_xPreEval - Pre-Evaluation
* ------------------------------------------------------------
*/
SG_RET_CODE SG_xPreEval_Graphics_Solid(SG_OBJ *const self,
          SG_OBJ *const simCtrl, SG_OBJ *const chgChild,
          SG_OBJ *const refObjs[], const INT *const piRefObjs,
          SG_OBJ *const adjObjs[], const INT *const piAdjObjs,
          SG_OBJ *const lnkObjs[], const INT *const piLnkObjs,
          TCHAR *const cMessage, const INT iMsgLen,
          TCHAR *const cCommand, const INT iCmdLen,
          SG_FILE *const pOutFile )
{
    /* TODO: declare your local variables here */

    INT iWidth = self->zValues[SG_NDX_IWINSIZE].iData[0];
    INT iHeight = self->zValues[SG_NDX_IWINSIZE].iData[1];
    FLOAT *fScale = &self->zValues[SG_NDX_FSCALE].fData[0];
    FLOAT *fTrans = &self->zValues[SG_NDX_FTRANSLATE].fData[0];
    GLfloat fRange = 100.f;
    GLfloat fRatio = (iWidth <= iHeight) ?
                     fRange * (GLfloat)iHeight / (GLfloat)iWidth :
                     fRange * (GLfloat)iWidth / (GLfloat)iHeight;
    GLfloat fScaleFac = 30.f * fScale[2]; /* use only Z scaling factor */

    if (!SG_IsSchemaOK(self->nSGobjSchema))
        return SG_R_SCHM;

    /* TODO: put your simulator code here */

    /* NOTE: When the SG_STAT_EDIT bit is set, this routine is called by the
     * SansGUI Framework in the case that the graphics window is being
     * resized. If the bit is not set, this routine is called during
     * a simulation run and only when the screen refreshing cycle is
     * reached.
     */
    if (SG_IsEditing(self->iStatus))
    {
        /* Set Viewport to window's full client area */
        glViewport(0, 0, (GLsizei)iWidth, (GLsizei)iHeight);

        /* Reset coordinate system */
        glMatrixMode(GL_PROJECTION);
        glLoadIdentity();

        /* Establish clipping volume (left, right, bottom, top, near, far) */
        if (iWidth <= iHeight)
            glOrtho(-fRange, fRange, -fRatio, fRatio, -fRange, fRange);
        else
            glOrtho(-fRatio, fRatio, -fRange, fRange, -fRange, fRange);

        /* Set up transformation to move objects away from the origin */
        /* SansGUI normalizes X and Y elements to the range [-1..1] */
        glTranslatef((GLfloat)fTrans[0] * 100.f, (GLfloat)fTrans[1] * 100.f,
                     (GLfloat)-5.f );

        /* Respond to user selected zoom factor, apply fScale universally */
        /* The developer can use X and Y elements for their own purposes */
        glScalef(fScaleFac, fScaleFac, fScaleFac);

        glMatrixMode(GL_MODELVIEW);
    }

    return SG_R_OK;
}

/* ============================================================
* SG_xEval - Evaluation
* ------------------------------------------------------------
*/
SG_RET_CODE SG_xEval_Graphics_Solid(SG_OBJ *const self,
          SG_OBJ *const simCtrl, SG_OBJ *const chgChild,
          SG_OBJ *const refObjs[], const INT *const piRefObjs,
          SG_OBJ *const adjObjs[], const INT *const piAdjObjs,
          SG_OBJ *const lnkObjs[], const INT *const piLnkObjs,
          TCHAR *const cMessage, const INT iMsgLen,
          TCHAR *const cCommand, const INT iCmdLen,
          SG_FILE *const pOutFile )
{
    /* TODO: declare your local variables here */

    FLOAT* fRotate = &self->zValues[SG_NDX_FROTATE].fData[0];
    FLOAT* fAngle = &self->zValues[SG_NDX_FANGLE].fData[0];
    INT* iSelect = &self->zValues[SG_NDX_ISELECT].iData[0];

    if (!SG_IsSchemaOK(self->nSGobjSchema))
        return SG_R_SCHM;

    /* TODO: put your simulator code here */

    /* NOTE: When the SG_STAT_EDIT bit is set, this routine is called by the
     * SansGUI Framework in the case that the user made a selection
     * rectangle or, in a special case, a selection point. If the bit
     * is not set, this routine is called during a simulation run with
     * the regular SansGUI DLL function call semantics.
     */
    if (SG_IsEditing(self->iStatus))
    {   /* when the user selected a rectangular area of the graphics window */
        /* iSelect[4] is an integer array containing four elements, or two
         * pairs of X-Y coordinates corresponding to two corners of the user
         * selection box:
         * iSelect[0] - the X coordinate of the selection area when the mouse
         * button is down
         * iSelect[1] - the Y coordinate of the selection area when the mouse
         * button is down
         * iSelect[2] - the X coordinate of the selection area when the mouse
         * button is released
         * iSelect[3] - the Y coordinate of the selection area when the mouse
         * button is released
         * The values of these coordinates are not normalized, meaning that
         * they are raw window coordinates in pixels (0, 0 at upper left
         * corner of the graphics window) and reflecting the first and the
         * second points of the rectangular area the user selected. They are
         * NOT sorted to reflect upper-left and then lower-right corners.
         * When the user clicks on a point without dragging, the two points
         * contains the same coordinate pair.
         */
        sprintf(cMessage, "user selection is (%d, %d) (%d, %d)",
                iSelect[0], iSelect[1], iSelect[2], iSelect[3] );
        /* In this example, we simply let SansGUI to display the message. The
         * number 17 is just an arbitary message code defined by the developer.
         * the message will be displayed in the Message View at the bottom pane
         * of the document window within SansGUI.
         */
        return (SG_R_LMSG | 17);
    }
    else
    {   /* when this routine is called in a simulation run, simply rotate the object */
        *fAngle = fRotate[1] + 5.f; /* use rotation angle about Y axis */
        /* when the angle reaches beyond 180, find its equivalent negative angle */
        if (*fAngle > 180.f)
            *fAngle = -(360.f - *fAngle);
        fRotate[1] = *fAngle; /* rotate about the Y (vertical) axis */
    }

    return SG_R_OK;
}

/* ============================================================
* SG_xPostEval - Post-Evaluation
* ------------------------------------------------------------
*/
SG_RET_CODE SG_xPostEval_Graphics_Solid(SG_OBJ *const self,
          SG_OBJ *const simCtrl, SG_OBJ *const chgChild,
          SG_OBJ *const refObjs[], const INT *const piRefObjs,
          SG_OBJ *const adjObjs[], const INT *const piAdjObjs,
          SG_OBJ *const lnkObjs[], const INT *const piLnkObjs,
          TCHAR *const cMessage, const INT iMsgLen,
          TCHAR *const cCommand, const INT iCmdLen,
          SG_FILE *const pOutFile )
{
    /* TODO: declare your local variables here */

    FLOAT *fRotate = &self->zValues[SG_NDX_FROTATE].fData[0];
    const INT iShape = self->zValues[SG_NDX_ISHAPE].iData[0];
    const INT iType = self->zValues[SG_NDX_ITYPE].iData[0];
    const INT iColor = self->zValues[SG_NDX_ICOLOR].iData[0];

    if (!SG_IsSchemaOK(self->nSGobjSchema))
        return SG_R_SCHM;

    /* TODO: put your simulator code here */

    /* NOTE: When the SG_STAT_EDIT bit is set, this routine is called by the
     * SansGUI Framework in the case that the graphics window needs to
     * be redrawn, as to render the scene. If the bit is not set, this
     * routine is called during a simulation run and only when the
     * screen refreshing cycle is reached.
     *
     * In this example, we perform scene rendering whether the SG_STAT_EDIT
     * bit is set or not.
     */

    /* Clear the window with current clearing color */
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

    /* Save the original matrix */
    glPushMatrix();

    /* Rotate the object back to (0, 0, 0) to rotate with absolute angles */
    glLoadIdentity();

    /* Do rotation with absolute angles */
    glRotatef((GLfloat)fRotate[0], 1.0f, 0.0f, 0.0f);
    glRotatef((GLfloat)fRotate[1], 0.0f, 1.0f, 0.0f);
    glRotatef((GLfloat)fRotate[2], 0.0f, 0.0f, 1.0f);

    switch (iColor)
    {
    case COLOR_CYAN:
        glColor3f(0.0f, 1.0f, 1.0f);
        break;
    case COLOR_MAGENTA:
        glColor3f(1.0f, 0.0f, 1.0f);
        break;
    case COLOR_YELLOW:
        glColor3f(1.0f, 1.0f, 0.0f);
        break;
    default: /* white object */
        glColor3f(1.0f, 1.0f, 1.0f);
        break;
    }

    switch (iShape)
    {
    case SHAPE_TETRAHEDRON:
        if (iType == 0)
            auxSolidTetrahedron(2.0f);
        else
            auxWireTetrahedron(2.0f);
        break;
    case SHAPE_CUBE:
        if (iType == 0)
            auxSolidCube(2.0f);
        else
            auxWireCube(2.0f);
        break;
    case SHAPE_OCTAHEDRON:
        if (iType == 0)
            auxSolidOctahedron(1.5f);
        else
            auxWireOctahedron(1.5f);
        break;
    case SHAPE_DODECAHEDRON:
        if (iType == 0)
            auxSolidDodecahedron(1.5f);
        else
            auxWireDodecahedron(1.5f);
        break;
    case SHAPE_ICOSAHEDRON:
        if (iType == 0)
            auxSolidIcosahedron(1.5f);
        else
            auxWireIcosahedron(1.5f);
        break;
    case SHAPE_BOX:
        if (iType == 0)
            auxSolidBox(2.0f, 1.0f, 3.0f);
        else
            auxWireBox(2.0f, 1.0f, 3.0f);
        break;
    case SHAPE_CYLINDER:
        if (iType == 0)
            auxSolidCylinder(1.0f, 2.0f);
        else
            auxWireCylinder(1.0f, 2.0f);
        break;
    case SHAPE_CONE:
        if (iType == 0)
            auxSolidCone(1.0f, 2.0f);
        else
            auxWireCone(1.0f, 2.0f);
        break;
    case SHAPE_SPHERE:
        if (iType == 0)
            auxSolidSphere(1.0f);
        else
            auxWireSphere(1.0f);
        break;
    case SHAPE_TORUS:
        if (iType == 0)
            auxSolidTorus(1.0f, 2.0f);
        else
            auxWireTorus(1.0f, 2.0f);
        break;
    case SHAPE_TEAPOT:
        if (iType == 0)
            auxSolidTeapot(2.0f);
        else
            auxWireTeapot(2.0f);
        break;
    default:
        /* blank screen, should not have come to this point */
        break;
    }

    /* Restore the original matrix */
    glPopMatrix();

    /* Flush drawing commands */
    glFlush();

    return SG_R_OK;
}

 


SansGUI Modeling and Simulation Environment version 1.2

Copyright © 2000-2003 ProtoDesign, Inc. All rights reserved.

http://protodesign-inc.com