Source/Process.c

/****************************/
/*      PROCESS.C           */
/* By Brian Greenstone      */
/****************************/
 
 
/****************************/
/*    EXTERNALS             */
/****************************/
 
#include <QD3D.h>
#include <QD3DGeometry.h>
#include <QD3DGroup.h>
#include <QD3DMath.h>
 
#include "myglobals.h"
#include "objects.h"
#include "mymenus.h"
#include "mywindows.h"
#include "myevents.h"
#include "misc.h"
#include "process.h"
#include "qd3d_support.h"
#include "3dmf.h"
 
extern  NewObjectDefinitionType gNewObjectDefinition;
extern  float               gFramesPerSecond;
 
 
/****************************/
/*    PROTOTYPES            */
/****************************/
 
static void InitModelWindow(void);
static void CalcBBox(TQ3Object theObject, TQ3BoundingBox    *bbox);
static void BuildTriMeshTest(void);
static void BuildBBoxOutline(TQ3DisplayGroupObject group, TQ3BoundingBox *bbox);
static void MoveCamera(void);
static void BuildSphereTest(void);
static void BuildTorusTest(void);
 
 
/****************************/
/*    CONSTANTS             */
/****************************/
 
#define MODEL_WIND_ID           400
 
 
/*********************/
/*    VARIABLES      */
/*********************/
 
WindowPtr               gModelWindow = nil;
QD3DSetupOutputType     gModelViewInfo;
TQ3DisplayGroupObject   gModelGroup[NUM_TEST] = {nil,nil,nil,nil,nil};
 
TQ3Point3D          gCameraFrom = { 0,0, .1 };
 
Boolean             gUseCullingGroups = kQ3True;
Boolean             gShowBBoxes = kQ3True;
 
int                 gCurrentTest = TEST_TRIMESH;
 
 
/******************** INIT TEST ************************/
 
void InitTest(void)
{
 
            /* INIT THE WINDOW */
            
    InitModelWindow();
 
 
            /* CREATE THE TEST MODEL */
            
    BuildCurrentTest();
 
    QD3D_CalcFramesPerSecond();
}
 
 
 
/************** INIT MODEL WINDOW *******************/
 
static void InitModelWindow(void)
{
QD3DSetupInputType  viewDef;
TQ3Point3D          cameraTo = { 0, 0, 0 };
TQ3Vector3D         cameraUp = { 0.0, 1.0, 0 };
TQ3ColorARGB        clearColor = {1,0,0,0};
TQ3ColorRGB         ambientColor = { 1.0, 1.0, 1.0 };
TQ3Vector3D         fillDirection1 = {1, -.3, -.8 };
TQ3Vector3D         fillDirection2 = { -1, -.1, -.2 };
 
 
            /* CREATE THE WINDOW */
            
    gModelWindow = GetNewCWindow(MODEL_WIND_ID, NIL_POINTER,MOVE_TO_FRONT);
    if (gModelWindow == nil)
        DoFatalAlert("\pWhere did the GameWindow window go?");                  
    SetPort((GrafPtr)gModelWindow);
 
 
            /***********************/
            /* SET QD3D PARAMETERS */
            /***********************/
 
    viewDef.view.displayWindow      = gModelWindow;
    viewDef.view.rendererType       = kQ3RendererTypeInteractive;
    viewDef.view.clearColor         = clearColor;
    viewDef.view.paneClip.left      = 0;
    viewDef.view.paneClip.right     = 0;
    viewDef.view.paneClip.top       = 0;
    viewDef.view.paneClip.bottom    = 0; 
 
    viewDef.styles.interpolation    = kQ3InterpolationStyleVertex; 
    viewDef.styles.backfacing       = kQ3BackfacingStyleBoth;
    viewDef.styles.fill             = kQ3FillStyleFilled; 
    viewDef.styles.illuminationType = kQ3IlluminationTypePhong; 
 
    viewDef.camera.from             = gCameraFrom;
    viewDef.camera.to               = cameraTo;
    viewDef.camera.up               = cameraUp;
    viewDef.camera.hither           = 5;
    viewDef.camera.yon              = 1500;
    viewDef.camera.fov              = .9;
 
    viewDef.lights.ambientBrightness = 0.3;
    viewDef.lights.ambientColor     = ambientColor;
    viewDef.lights.numFillLights    = 2;
    viewDef.lights.fillDirection[0] = fillDirection1;
    viewDef.lights.fillDirection[1] = fillDirection2;
    viewDef.lights.fillColor[0]     = ambientColor;
    viewDef.lights.fillColor[1]     = ambientColor;
    viewDef.lights.fillBrightness[0] = .8;
    viewDef.lights.fillBrightness[1] = 0.4;
 
 
    QD3D_SetupWindow(&viewDef, &gModelViewInfo);
 
}
 
 
/******************** BUILD CURRENT TEST *************************/
 
void BuildCurrentTest(void)
{
ObjNode *newObj;
float       x,y,z;
    
    switch(gCurrentTest)
    {
        case    TEST_TRIMESH:
                BuildTriMeshTest();
                break;
 
        case    TEST_SPHERE:
                BuildSphereTest();
                break;
    
        case    TEST_TORUS:
                BuildTorusTest();
                break;
    
        default:
                return;
    }
 
 
    DeleteAllObjects();
 
    for (x = -1000; x < 1000; x += 300)
        for (y = -1000; y < 1000; y += 300)
            for (z = -1000; z < 1000; z += 300)
            {
                        /* CREATE OBJNODE */
                        
                gNewObjectDefinition.genre = DISPLAY_GROUP_GENRE;               
                gNewObjectDefinition.coord.x = x;
                gNewObjectDefinition.coord.y = y;
                gNewObjectDefinition.coord.z = z;
                gNewObjectDefinition.flags = OBJ_MODE_DRAW;
                gNewObjectDefinition.slot = 100;
                gNewObjectDefinition.moveCall = nil;
                newObj = MakeNewDisplayGroupObject(&gNewObjectDefinition);
 
                AttachGeometryToDisplayGroupObject(newObj,gModelGroup[gCurrentTest]);
 
                UpdateObjectTransforms(newObj);
            }
    
    
    DrawModelWindow();
 
}
 
 
/******************* DRAW MODEL WINDOW *********************/
//
// Calls the support function QD3D_DrawScene.
// It passes the view info and a pointer to the game draw callback.
//
 
void DrawModelWindow(void)
{
    QD3D_DrawScene(&gModelViewInfo,(void *)DrawObjects);
}
 
 
 
/*************** DO MODEL WINDOW NULL EVENT **********************/
 
void DoModelWindowNullEvent(void)
{
    QD3D_CalcFramesPerSecond();
    MoveObjects();
    MoveCamera();
    DrawModelWindow();
}
 
 
 
/****************** UPDATE MODEL WINDOW ******************/
//
// Called when there is an update event from the event manager
//
 
void UpdateModelWindow(void)
{
    DrawModelWindow();  
}
 
 
 
 
/**************** MOVE CAMERA *****************/
 
static void MoveCamera(void)
{
TQ3Matrix4x4    m;
 
    Q3Matrix4x4_SetRotate_XYZ(&m,
                     1.0f/gFramesPerSecond * .1f,   
                     0, 
                     1.1f/gFramesPerSecond * -.15f);    
 
    
    Q3Point3D_Transform(&gCameraFrom, &m, &gCameraFrom);
    QD3D_UpdateCameraFrom(&gModelViewInfo, &gCameraFrom);
}
 
 
 
 
/*********************** BUILD TRIMESH TEST **************************/
 
static void BuildTriMeshTest(void)
{
TQ3Object   obj;
FSSpec      spec;
TQ3DisplayGroupState    state;
TQ3BoundingBox  bbox;
 
                /* NUKE OLD ONE */
            
    if (gModelGroup[TEST_TRIMESH])
        Q3Object_Dispose(gModelGroup[TEST_TRIMESH]);
 
 
            /* LOAD TRIMESH FROM FILE */
            
    FSMakeFSSpec(0, 0, "\p:data:tree.3dmf", &spec);
//  FSMakeFSSpec(0, 0, "\p:data:rex.3dmf", &spec);
    obj = Load3DMFModel(&spec);
        
        
            /* SEE IF OBJECT IS A GROUP ALREADY */
        
    if (Q3Object_IsType(obj,kQ3ShapeTypeGroup))
    {
        gModelGroup[TEST_TRIMESH] = obj;    
    }
    
            /* MAKE NEW GROUP & PUT OBJ IN IT */
    else
    {               
        gModelGroup[TEST_TRIMESH] = Q3DisplayGroup_New();
        Q3Group_AddObject(gModelGroup[TEST_TRIMESH],obj);
        Q3Object_Dispose(obj);
    }
    
    
            /* MAKE GROUP INLINE & ASSIGN BBOX */
                
    if (gUseCullingGroups)
    {       
        Q3DisplayGroup_CalcAndUseBoundingBox(gModelGroup[TEST_TRIMESH],     // calc & set group's bbox
                                            kQ3ComputeBoundsExact,
                                            gModelViewInfo.viewObject);     
        Q3DisplayGroup_GetState(gModelGroup[TEST_TRIMESH],&state);          // make inline
        state |= kQ3DisplayGroupStateMaskIsInline;
        Q3DisplayGroup_SetState(gModelGroup[TEST_TRIMESH],state);       
    }   
 
    if (gShowBBoxes)
    {
        if (gUseCullingGroups)
            Q3DisplayGroup_GetBoundingBox(gModelGroup[TEST_TRIMESH], &bbox);
        else
            CalcBBox(gModelGroup[TEST_TRIMESH], &bbox);
        BuildBBoxOutline(gModelGroup[TEST_TRIMESH],&bbox);
    }
}
 
 
 
/**************** CALC BOUNDING BOX ***********************/
 
static void CalcBBox(TQ3Object theObject, TQ3BoundingBox    *bbox)
{
TQ3Status   status;
 
    status = Q3View_StartBoundingBox(gModelViewInfo.viewObject, kQ3ComputeBoundsExact);
    if (status == kQ3Failure)
        DoFatalAlert("\pCalcBBox: Q3View_StartBoundingBox");
    do
    {
        status = Q3Object_Submit(theObject,gModelViewInfo.viewObject);
        if (status == kQ3Failure)
            DoFatalAlert("\pCalcBBox: Q3View_StartBoundingBox");
 
    }while(Q3View_EndBoundingBox(gModelViewInfo.viewObject, bbox) == kQ3ViewStatusRetraverse);
}
 
 
 
/****************** BUILD BBOX OUTLINE **********************/
 
static void BuildBBoxOutline(TQ3DisplayGroupObject group, TQ3BoundingBox *bbox)
{
TQ3Object       line;
TQ3PolyLineData data;
TQ3LineData     data2;
TQ3Vertex3D     verts[5];
 
    data.numVertices = 5;
    data.vertices = &verts[0];
    data.segmentAttributeSet = nil;
    data.polyLineAttributeSet = nil;
    verts[0].attributeSet = nil;
    verts[1].attributeSet = nil;
    verts[2].attributeSet = nil;
    verts[3].attributeSet = nil;
 
                /* BACK */
                
    verts[0].point = bbox->min;             // lower left far
    verts[4] = verts[0];
    
    verts[1] = verts[0];
    verts[1].point.x = bbox->max.x;         // lower right far
    
    verts[2] = verts[1];
    verts[2].point.y = bbox->max.y;         // upper right far
    
    verts[3] = verts[2];
    verts[3].point.x = bbox->min.x;             // upper left far
 
    line = Q3PolyLine_New(&data);           // make new polyline
    Q3Group_AddObject(group,line);
    Q3Object_Dispose(line);
 
                /* FRONT */
                
    verts[0].point = bbox->max;             // upper right near
    verts[4] = verts[0];
    
    verts[1] = verts[0];
    verts[1].point.x = bbox->min.x;         // upper left near
    
    verts[2] = verts[1];
    verts[2].point.y = bbox->min.y;         // lower left near
    
    verts[3] = verts[2];
    verts[3].point.x = bbox->max.x;         // lower right near
 
    line = Q3PolyLine_New(&data);           // make new polyline
    Q3Group_AddObject(group,line);
    Q3Object_Dispose(line);
 
 
        /* LOWER LEFT SPAR */
        
    data2.lineAttributeSet = nil;
    data2.vertices[0].attributeSet = nil;
    data2.vertices[1].attributeSet = nil;
    
    data2.vertices[0].point = bbox->min;                    // lower left far
    data2.vertices[1].point = data2.vertices[0].point;
    data2.vertices[1].point.z = bbox->max.z;                // lower left near
    
    line = Q3Line_New(&data2);
    Q3Group_AddObject(group,line);
    Q3Object_Dispose(line);
 
 
        /* LOWER RIGHT SPAR */
            
    data2.vertices[0].point.x = bbox->max.x;                    // lower right far
    data2.vertices[1].point.x = data2.vertices[0].point.x;  // lower right near
                    
    line = Q3Line_New(&data2);
    Q3Group_AddObject(group,line);
    Q3Object_Dispose(line);
 
 
        /* UPPER RIGHT SPAR */
            
    data2.vertices[0].point.y = bbox->max.y;                // upper right far
    data2.vertices[1].point.y = data2.vertices[0].point.y;  // lower right near
                    
    line = Q3Line_New(&data2);
    Q3Group_AddObject(group,line);
    Q3Object_Dispose(line);
 
 
        /* UPPER LEFT SPAR */
            
    data2.vertices[0].point.x = bbox->min.x;                // upper left far
    data2.vertices[1].point.x = data2.vertices[0].point.x;  // lower left near
                    
    line = Q3Line_New(&data2);
    Q3Group_AddObject(group,line);
    Q3Object_Dispose(line);
 
}
 
 
 
 
 
 
/*********************** BUILD SPHERE TEST **************************/
 
static void BuildSphereTest(void)
{
TQ3EllipsoidData    data;
TQ3Object   obj;
TQ3DisplayGroupState    state;
TQ3BoundingBox  bbox;
 
                /* NUKE OLD ONE */
            
    if (gModelGroup[TEST_SPHERE])
        Q3Object_Dispose(gModelGroup[TEST_SPHERE]);
 
 
            /* BUILD THE SPHERE */
            
    data.ellipsoidAttributeSet = nil;
    data.interiorAttributeSet = nil;
    data.origin.x = data.origin.y = data.origin.z = 0;
    data.orientation.x = 0;
    data.orientation.y = 80;
    data.orientation.z = 0;
    data.majorRadius.x = 0;
    data.majorRadius.y = 0;
    data.majorRadius.z = 80;
    data.minorRadius.x = 80;
    data.minorRadius.y = 0;
    data.minorRadius.z = 0; 
    data.uMax = data.vMax = 1.0;
    data.uMin = data.vMin = 0;
    data.caps = kQ3EndCapNone;
    
    obj = Q3Ellipsoid_New(&data);
    if (obj == nil)
        DoFatalAlert("\pBuildSphereTest: Q3Ellipsoid_New");
 
        
    
            /* MAKE NEW GROUP & PUT OBJ IN IT */
 
    gModelGroup[TEST_SPHERE] = Q3DisplayGroup_New();
    if (gModelGroup[TEST_SPHERE] == nil)
        DoFatalAlert("\pBuildSphereTest: Q3DisplayGroup_New");
    
    Q3Group_AddObject(gModelGroup[TEST_SPHERE],obj);
    Q3Object_Dispose(obj);
    
    
    
            /* MAKE GROUP INLINE & ASSIGN BBOX */
                
    if (gUseCullingGroups)
    {       
        Q3DisplayGroup_CalcAndUseBoundingBox(gModelGroup[TEST_SPHERE],      // calc & set group's bbox
                                            kQ3ComputeBoundsExact,
                                            gModelViewInfo.viewObject);     
        Q3DisplayGroup_GetState(gModelGroup[TEST_SPHERE],&state);           // make inline
        state |= kQ3DisplayGroupStateMaskIsInline;
        Q3DisplayGroup_SetState(gModelGroup[TEST_SPHERE],state);        
    }   
    
    if (gShowBBoxes)
    {
        if (gUseCullingGroups)
            Q3DisplayGroup_GetBoundingBox(gModelGroup[TEST_SPHERE], &bbox);
        else
            CalcBBox(gModelGroup[TEST_SPHERE], &bbox);
        BuildBBoxOutline(gModelGroup[TEST_SPHERE],&bbox);
    }
    
}
 
 
 
 
/*********************** BUILD TORUS TEST **************************/
 
static void BuildTorusTest(void)
{
TQ3TorusData    data;
TQ3Object   obj;
TQ3DisplayGroupState    state;
TQ3BoundingBox  bbox;
 
                /* NUKE OLD ONE */
            
    if (gModelGroup[TEST_TORUS])
        Q3Object_Dispose(gModelGroup[TEST_TORUS]);
 
 
            /* BUILD THE SPHERE */
            
    data.torusAttributeSet = nil;
    data.interiorAttributeSet = nil;
    data.origin.x = data.origin.y = data.origin.z = 0;
    data.orientation.x = 0;
    data.orientation.y = 50;
    data.orientation.z = 0;
    data.majorRadius.x = 0;
    data.majorRadius.y = 0;
    data.majorRadius.z = 40;
    data.minorRadius.x = 80;
    data.minorRadius.y = 0;
    data.minorRadius.z = 0;
    data.ratio = .4;
    data.uMax = data.vMax = 1.0;
    data.uMin = data.vMin = 0;
    data.caps = kQ3EndCapNone;
    
    obj = Q3Torus_New(&data);
    if (obj == nil)
        DoFatalAlert("\pBuildTorusTest: Q3Torus_New");
 
        
    
            /* MAKE NEW GROUP & PUT OBJ IN IT */
 
    gModelGroup[TEST_TORUS] = Q3DisplayGroup_New();
    if (gModelGroup[TEST_TORUS] == nil)
        DoFatalAlert("\pBuildSphereTest: Q3DisplayGroup_New");
    
    Q3Group_AddObject(gModelGroup[TEST_TORUS],obj);
    Q3Object_Dispose(obj);
    
    
            /* MAKE GROUP INLINE & ASSIGN BBOX */
                
    if (gUseCullingGroups)
    {       
        Q3DisplayGroup_CalcAndUseBoundingBox(gModelGroup[TEST_TORUS],       // calc & set group's bbox
                                            kQ3ComputeBoundsExact,
                                            gModelViewInfo.viewObject);     
        Q3DisplayGroup_GetState(gModelGroup[TEST_TORUS],&state);            // make inline
        state |= kQ3DisplayGroupStateMaskIsInline;
        Q3DisplayGroup_SetState(gModelGroup[TEST_TORUS],state);     
    }   
 
    if (gShowBBoxes)
    {
        if (gUseCullingGroups)
            Q3DisplayGroup_GetBoundingBox(gModelGroup[TEST_TORUS], &bbox);
        else
            CalcBBox(gModelGroup[TEST_TORUS], &bbox);
        BuildBBoxOutline(gModelGroup[TEST_TORUS],&bbox);
    }
 
}