/*---------------------------------------------------------------------------* Project: Dolphin/Revolution gx demo File: tf-reflect.c Copyright 1998-2006 Nintendo. All rights reserved. These coded instructions, statements, and computer programs contain proprietary information of Nintendo of America Inc. and/or Nintendo Company Ltd., and are protected by Federal copyright law. They may not be disclosed to third parties or copied or duplicated in any form, in whole or in part, without the prior written consent of Nintendo. *---------------------------------------------------------------------------*/ #include #include /*---------------------------------------------------------------------------* Macro definitions *---------------------------------------------------------------------------*/ #define VP_ASPECT ((float)4/(float)3) /*---------------------------------------------------------------------------* Forward references *---------------------------------------------------------------------------*/ void DrawScene( void ); void myDrawModel( void ); void myAnimeModel( void ); /*---------------------------------------------------------------------------* Rendering parameters *---------------------------------------------------------------------------*/ typedef struct { Point3d position; Point3d target; Vec up; f32 fovy; f32 znear; f32 zfar; Mtx viewMtx; } Camera; Camera myCamera = { { 0.0f, -400.0f, 0.0f }, // position { 0.0f, 0.0f, 0.0f }, // target { 0.0f, 0.0f, 1.0f }, // upVec 33.3f, // fovy 128.0f, // near plane Z in camera coordinates 2048.0f, // far plane Z in camera coordinates }; TPLPalettePtr texPalette = 0; GXTexObj texObj; /*---------------------------------------------------------------------------* Application main loop *---------------------------------------------------------------------------*/ void main ( void ) { GXColor grey = {128,128,128,0}; // initialize render settings and set clear color for first frame DEMOInit( NULL ); // Defined in $(REVOLUTION_SDK_ROOT)/build/libraries/demo/src/DEMOInit.c OSReport("\n\n"); OSReport("**********************************************\n"); OSReport("tf-reflect: Reflection mapping demo\n"); OSReport("**********************************************\n"); OSReport("To quit hit the start button.\n"); OSReport("\n"); OSReport("Main stick rotates model.\n"); OSReport("A/B buttons control camera zoom.\n"); OSReport("L/R triggers control pipe bend.\n"); OSReport("**********************************************\n"); OSReport("\n\n"); GXInvalidateTexAll( ); GXSetCopyClear( grey, GX_MAX_Z24 ); // Image on fish eye camera view TPLGetPalette( &texPalette, "gxTests/tf-02.tpl" ); TPLGetGXTexObjFromPalette( texPalette, &texObj, 1 ); while ( ! ( DEMOPadGetButton(0) & PAD_BUTTON_MENU ) ) { // get pad status DEMOPadRead( ); // General control & model animation myAnimeModel( ); // Draw scene DEMOBeforeRender( ); DrawScene( ); DEMODoneRender( ); } OSHalt("End of test"); } //--------------------------------------------------------------------------- // Model settings //--------------------------------------------------------------------------- typedef struct { s8 x, y; s8 nx, ny, nz; s8 pad; } MyVertex; static MyVertex ringVtx[] ATTRIBUTE_ALIGN(32) = { { 100, 0, 64, 0, 0 }, /* 0 */ { 87, 50, 55, 32, 0 }, /* 30 */ { 50, 87, 32, 55, 0 }, /* 60 */ { 0, 100, 0, 64, 0 }, /* 90 */ { -50, 87, -32, 55, 0 }, /* 120 */ { -87, 50, -55, 32, 0 }, /* 150 */ {-100, 0, -64, 0, 0 }, /* 180 */ { -87, -50, -55, -32, 0 }, /* 210 */ { -50, -87, -32, -55, 0 }, /* 240 */ { 0,-100, 0, -64, 0 }, /* 270 */ { 50, -87, 32, -55, 0 }, /* 300 */ { 87, -50, 55, -32, 0 }, /* 330 */ }; #define VTXINRING ((s32)(sizeof(ringVtx)/sizeof(ringVtx[0]))) #define NUMPIPES 64 #define NUMRINGS (NUMPIPES+1) f32 pipeAngle = 10.0f; f32 pipeLength = 50.0f; Mtx pipeLocalMtx = { { 0.0646906f, 0.0760343f, 0.0058220f, 0.0f }, {-0.0740718f, 0.0608390f, 0.0284950f, 0.0f }, { 0.0181239f,-0.0227461f, 0.0956772f, 0.0f } }; // For Pos/Tex Matrix Array Mtx pipePosMtx[NUMRINGS] ATTRIBUTE_ALIGN(32); Mtx pipeTexMtx[NUMRINGS] ATTRIBUTE_ALIGN(32); //--------------------------------------------------------------------------- // Draw entire scene //--------------------------------------------------------------------------- void DrawScene( void ) { Mtx44 projMtx; Camera* c = &myCamera; // Set projection matrix MTXPerspective( projMtx, c->fovy, VP_ASPECT, c->znear, c->zfar ); GXSetProjection( projMtx, GX_PERSPECTIVE ); // Set rendering mode GXSetBlendMode( GX_BM_BLEND, GX_BL_ONE, GX_BL_ZERO, GX_LO_CLEAR ); GXSetZMode( GX_TRUE, GX_LESS, GX_TRUE ); GXSetZCompLoc( GX_TRUE ); // Set rendering mode GXSetCullMode( GX_CULL_BACK ); // Draw objects myDrawModel( ); return; } //--------------------------------------------------------------------------- // Animate model //--------------------------------------------------------------------------- # define MOVE_SCALE 1.0f void myAnimeModel( void ) { Camera* c = &myCamera; Mtx localMtx, tmpMtx; Vec axis; s32 i, j; f32 nfct; f32 zoom; Vec rotAxis = { 0.0f, 1.0f, 0.2f }; u16 buttons, stickDirs; axis.x = axis.y = axis.z = 0.0f; zoom = 0.0f; stickDirs = DEMOPadGetDirs(0); buttons = DEMOPadGetButton(0); if ( stickDirs & DEMO_STICK_UP ) axis.x -= 1.0f; if ( stickDirs & DEMO_STICK_DOWN ) axis.x += 1.0f; if ( stickDirs & DEMO_STICK_LEFT ) axis.y -= 1.0f; if ( stickDirs & DEMO_STICK_RIGHT ) axis.y += 1.0f; if ( buttons & PAD_BUTTON_A ) zoom = 2.0f * MOVE_SCALE; if ( buttons & PAD_BUTTON_B ) zoom = -2.0f * MOVE_SCALE; if ( buttons & PAD_TRIGGER_L ) pipeAngle += 0.1f; if ( buttons & PAD_TRIGGER_R ) pipeAngle -= 0.1f; //--------- Get View matrix c->position.y += zoom; MTXLookAt( c->viewMtx, &c->position, &c->up, &c->target ); //--------- Make local matrix MTXInverse( c->viewMtx, tmpMtx ); MTXMultVecSR( tmpMtx, &axis, &axis ); if ( axis.x != 0.0f || axis.y != 0.0f || axis.z != 0.0f ) { MTXRotAxisDeg( tmpMtx, &axis, 0.6f * MOVE_SCALE ); MTXConcat( tmpMtx, pipeLocalMtx, pipeLocalMtx ); } //--------- Get Position Matrix MTXConcat ( c->viewMtx, pipeLocalMtx, pipePosMtx[0] ); MTXTrans ( localMtx, 0, 0, pipeLength ); MTXRotAxisDeg( tmpMtx, &rotAxis, pipeAngle ); MTXConcat ( tmpMtx, localMtx, localMtx ); for ( i = 1; i < NUMRINGS; i ++ ) { MTXConcat( pipePosMtx[i-1], localMtx, pipePosMtx[i] ); } //--------- Get Texture Matrix for environment mapping for ( i = 0; i < NUMRINGS; i ++ ) { for ( j = 0; j < 2; j ++ ) { nfct = 0.5f / VECMag( (VecPtr)pipePosMtx[i][0] ); if ( j == 1 ) nfct = -nfct; pipeTexMtx[i][j][0] = pipePosMtx[i][j][0] * nfct; pipeTexMtx[i][j][1] = pipePosMtx[i][j][1] * nfct; pipeTexMtx[i][j][2] = pipePosMtx[i][j][2] * nfct; pipeTexMtx[i][j][3] = 0.5f; } } DCFlushRange( pipePosMtx, sizeof(pipePosMtx) ); DCFlushRange( pipeTexMtx, sizeof(pipeTexMtx) ); } //--------------------------------------------------------------------------- // Draw model //--------------------------------------------------------------------------- void myDrawModel( void ) { s32 i, j, k; GXPosNrmMtx pm0, pm1; GXTexMtx tm0, tm1; GXColor black = { 0, 0, 0, 0 }; GXColor color = { 255, 128, 64, 255 }; //--------- Set rendering parameters GXSetChanCtrl( GX_COLOR0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_CLAMP, GX_AF_NONE ); GXSetChanCtrl( GX_ALPHA0, GX_DISABLE, GX_SRC_REG, GX_SRC_REG, GX_LIGHT_NULL, GX_DF_CLAMP, GX_AF_NONE ); GXSetChanAmbColor( GX_COLOR0A0, black ); GXSetChanMatColor( GX_COLOR0A0, color ); GXSetNumTexGens ( 1 ); // # of Texgen proc GXSetNumChans ( 1 ); // # of Color Channel GXSetNumTevStages( 1 ); // # of Tev Stage GXSetTevOrder( GX_TEVSTAGE0, GX_TEXCOORD0, GX_TEXMAP0, GX_COLOR0A0 ); GXSetTevOp( GX_TEVSTAGE0, GX_MODULATE ); // Set texture GXLoadTexObj( &texObj, GX_TEXMAP0 ); //-------- Array base & stride setting GXSetArray( GX_POS_MTX_ARRAY, &pipePosMtx[0], sizeof( pipePosMtx[0] ) ); GXSetArray( GX_TEX_MTX_ARRAY, &pipeTexMtx[0], sizeof( pipeTexMtx[0] ) ); GXSetArray( GX_VA_POS, &ringVtx[0].x, sizeof( ringVtx[0] ) ); GXSetArray( GX_VA_NRM, &ringVtx[0].nx, sizeof( ringVtx[0] ) ); //-------- Vertex descriptor settings GXClearVtxDesc( ); GXSetVtxDesc( GX_VA_POS, GX_INDEX8 ); GXSetVtxDesc( GX_VA_NRM, GX_DIRECT ); GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_POS, GX_POS_XY, GX_S8, 0 ); GXSetVtxAttrFmt( GX_VTXFMT0, GX_VA_NRM, GX_NRM_XYZ, GX_S8, 6 ); //-------- Pipe lid 0 (Triangle fan) pm0 = GX_PNMTX0; tm0 = GX_TEXMTX0; GXLoadPosMtxIndx( 0, pm0 ); GXLoadTexMtxIndx( 0, tm0, GX_MTX2x4 ); GXSetCurrentMtx ( pm0 ); GXSetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_NRM, tm0 ); GXBegin( GX_TRIANGLEFAN, GX_VTXFMT0, VTXINRING ); for ( i = 0; i < VTXINRING; i ++ ) { GXPosition1x8( (u8)i ); GXNormal3s8 ( (s8)(ringVtx[i].nx/4), (s8)(ringVtx[i].ny/4), -60 ); } GXEnd( ); //-------- Pipe body (Triangle strip) GXSetVtxDesc( GX_VA_PNMTXIDX, GX_DIRECT ); GXSetVtxDesc( GX_VA_TEX0MTXIDX, GX_DIRECT ); GXSetVtxDesc( GX_VA_NRM, GX_INDEX8 ); for ( j = 0; j < NUMRINGS-1; j ++ ) { pm1 = ( pm0 == GX_PNMTX0 ) ? GX_PNMTX1 : GX_PNMTX0; tm1 = ( tm0 == GX_TEXMTX0 ) ? GX_TEXMTX1 : GX_TEXMTX0; GXLoadPosMtxIndx( (u16)(j+1), pm1 ); GXLoadTexMtxIndx( (u16)(j+1), tm1, GX_MTX2x4 ); GXBegin( GX_TRIANGLESTRIP, GX_VTXFMT0, (VTXINRING+1)*2 ); k = VTXINRING-1; for ( i = -1; i < VTXINRING; i ++ ) { GXMatrixIndex1x8( (u8)pm0 ); GXMatrixIndex1x8( (u8)tm0 ); GXPosition1x8 ( (u8)k ); GXNormal1x8 ( (u8)k ); GXMatrixIndex1x8( (u8)pm1 ); GXMatrixIndex1x8( (u8)tm1 ); GXPosition1x8 ( (u8)k ); GXNormal1x8 ( (u8)k ); k = i + 1; } GXEnd( ); pm0 = pm1; tm0 = tm1; } //-------- Pipe lid 1 (Triangle fan) GXSetVtxDesc( GX_VA_PNMTXIDX, GX_NONE ); GXSetVtxDesc( GX_VA_TEX0MTXIDX, GX_NONE ); GXSetVtxDesc( GX_VA_NRM, GX_DIRECT ); GXSetCurrentMtx( pm0 ); GXSetTexCoordGen( GX_TEXCOORD0, GX_TG_MTX2x4, GX_TG_NRM, tm0 ); GXBegin( GX_TRIANGLEFAN, GX_VTXFMT0, VTXINRING ); for ( i = 0; i < VTXINRING; i ++ ) { GXPosition1x8( (u8)(VTXINRING-1-i) ); GXNormal3s8 ( (s8)(ringVtx[i].nx/4), (s8)(ringVtx[i].ny/4), +60 ); } GXEnd( ); return; } /*======== End of tf-reflect.c ========*/