📄 tutori3d.c
字号:
// Set Diffused lighting
light_value.type = AEE3D_LIGHT_DIFFUSED;
light_value.direction = directionDiffused;
light_value.color = colorDiffused;
if(I3D_SetLight(pMe->m_p3D, &light_value) != SUCCESS)
{
return FALSE;
}
// Set Specular lighting
light_value.type = AEE3D_LIGHT_SPECULAR;
light_value.direction = directionSpecular;
light_value.color = colorSpecular;
if(I3D_SetLight(pMe->m_p3D, &light_value) != SUCCESS)
{
return FALSE;
}
// initialize transformMtx to the indentity. transformMtx is
// used as the transformation matrix for the models in the different
// tutorials.
if(I3DUtil_SetIdentityMatrix(pMe->m_p3DUtil, &pMe->transformMtx) != SUCCESS)
{
return FALSE;
}
// By default turn alpha blending off
if(I3D_Enable(pMe->m_p3D, AEE3D_CAPABILITY_BLENDING, FALSE) != SUCCESS)
{
return FALSE;
}
// By default turn perspective correction off
if(I3D_Enable(pMe->m_p3D, AEE3D_CAPABILITY_PERSPECTIVE_CORRECTION, FALSE) != SUCCESS)
{
return FALSE;
}
// Set default variable settings
pMe->showHelp = FALSE;
pMe->keyIsPressed = FALSE;
// translate defaults
pMe->rotateAxis = AEE3D_ROTATE_X;
pMe->translateAxis = AXIS_X;
// projection defaults
pMe->viewDepthPlane = NEAR_PLANE;
pMe->screenMapOp = XSCALE;
pMe->clipRectOp = UPPER_LX;
// lighting defaults
pMe->lightTypeOp = AEE3D_LIGHT_DIFFUSED;
pMe->lightDirColOp = LIGHT_X;
pMe->lightMaterialOp = MATERIAL_RED;
//texture and rendering
pMe->textureOp = TEXTURE_WRAP_S;
pMe->showTexture = FALSE;
pMe->textureID = IDB_TEXTURE_WOOD;
pMe->alphaEnabled = FALSE;
pMe->perspectiveCorrEnabled = FALSE;
pMe->xrot = 0;
pMe->yrot = 0;
pMe->zrot = 0;
pMe->drawModel = MODEL_MAN;
return TRUE;
}
/*===========================================================================
FUNCTION: TutorI3D_FreeAppData
DESCRIPTION
Required Brew function. This is called on Application
exit to free all module data. All program data should be
deallocated before returning from this function.
PROTOTYPE:
void TutorI3D_FreeAppData (TutorI3D *pMe)
PARAMETERS:
pMe: [in]: Pointer to TutorI3D sturcture
DEPENDENCIES
none
RETURN VALUE
none
SIDE EFFECTS
none
===========================================================================*/
void TutorI3D_FreeAppData (TutorI3D *pMe)
{
if(!pMe)
return;
if(pMe->m_pIBitmapDDB)
IBITMAP_Release(pMe->m_pIBitmapDDB);
if(pMe->m_pGraphics)
IGRAPHICS_Release(pMe->m_pGraphics);
if(pMe->pModelField)
I3DModel_Release(pMe->pModelField);
if(pMe->pLadyBug)
I3DModel_Release(pMe->pLadyBug);
if(pMe->m_p3D)
I3D_Release(pMe->m_p3D);
if(pMe->m_p3DUtil)
I3DUtil_Release(pMe->m_p3DUtil);
if(pMe->axisModel)
Obj_FreeObj(pMe->axisModel);
if(pMe->cubeModel)
Obj_FreeObj(pMe->cubeModel);
if(pMe->sphereModel)
Obj_FreeObj(pMe->sphereModel);
if(pMe->pModelSmoothSphere)
I3DModel_Release(pMe->pModelSmoothSphere);
if(pMe->font10)
IFONT_Release(pMe->font10);
if(pMe->font11)
IFONT_Release(pMe->font11);
if(pMe->font11b)
IFONT_Release(pMe->font11b);
TutorI3D_CloseAllMenus(pMe);
}
/*===========================================================================
FUNCTION: TutorI3D_EventNotify
DESCRIPTION
This is the registered I3D event notifier callback. I3D calls back
to this function informing the user of the current
state of 3D rendering. This is a very IMPORTANT function,
as it tells the application when rendering for the current frame
begins, when it's ok to change geometry data, when it's ok to update
the current frame with 2D graphics and text, and also if there was
an error rendering a frame. Every I3D app must use this function.
PROTOTYPE:
void TutorI3D_EventNotify(TutorI3D * pMe, AEE3DEventNotify * pcn)
PARAMETERS:
pMe: [in]: Pointer to TutorI3D sturcture
pcn: [in]: Pointer to the event notify structure containing
event information
DEPENDENCIES
none
RETURN VALUE
none
SIDE EFFECTS
none
===========================================================================*/
void TutorI3D_EventNotify(TutorI3D * pMe, AEE3DEventNotify * pcn)
{
if(!pMe)
return;
switch(pcn->nEventType)
{
case AEE3D_EVENT_FRAME_STARTED:
//3D engine start to render current frame
//DBGPRINTF("3D engine start!");
break;
case AEE3D_EVENT_FRAME_COMPLETED:
//3D engine finish redering current frame
//can modify geometric data for next frame
//DBGPRINTF("3D engine frame completed");
// apply transformations depending on state and also apply
// any model data changes as it's safe to do so after receiving
// the AEE3D_EVENT_FRAME_COMPLETED event.
TutorI3D_UpdateTransformMtxAndModelData(pMe);
break;
case AEE3D_EVENT_FRAME_ERROR:
// there was an error on a frame,
DBGPRINTF("Frame Error!");
DBGPRINTF("Error Code: %d", pcn->nErrorCode);
// FALLTHROUGH and try rendering next frame if there was an error
// ..
// ..
case AEE3D_EVENT_FRAME_UPDATE_DISPLAY:
//frame buffer is ready for display. 2D overlays, etc. can be added
//before frame is displayed
//DBGPRINTF("3D frame buffer done -- ok to update screen!");
//DBGPRINTF("3D engine rendering done -- ok to modify model data!");
/* This function overlays 2D text and graphics to the frame,
and draws the frame to the screen
*/
TutorI3D_ManipulateBuf(pMe);
/* The code below is for going back a state.
We don't go back a state immediately when the user requests it.
Instead, we wait for the current frame to be completed then change states.
These state changes take place as a result of user input, ie. hitting
CLR while in a menu.
*/
if(pMe->changeState)
{
// if we're in here, the user has requested to change states
// by pressing the back key on a menu. We draw the new menu
// when the current frame has finished rendering which is now.
// get a pointer to the menu drawing function, based on the state
// we're going to.
PFN_DRAWMENUFUNC drawMenuFunc = GetDrawMenuFunction(pMe->nextState);
if(drawMenuFunc)
{
if(drawMenuFunc(pMe)) // was menu redrawn?
{
pMe->state = pMe->nextState; // set the state we're going to
pMe->changeState = FALSE; // reset the change state flag
pMe->nextState = STATE_NONE; // set nextState to none
}
else
{
DBGPRINTF("Error going to menu");
}
}
else
{
DBGPRINTF("Error getting the draw menu function");
}
}
/* If 'keyIsPressed' is TRUE, then we've received the EVT_KEY_PRESS event
but haven't received the EVT_KEY_RELEASE event, which means
a key is still pressed. We send an EVT_KEY_PRESS event to the corresponding
event handler, so that the proper action is taken again, while the key
is still pressed. This way, the user just needs to hold down the key,
and have the action repeated. They DON'T need to keep pressing and releasing
the key.
NOTE: In the SDK, BREW keeps resending the EVT_KEY_PRESS event while a key
is pressed, therefore the code below is not necessary for the SDK.
On the target however, BREW does not resend the EVT_KEY_PRESS event,
So you must manually take the proper action while the key is still down.
*/
#ifndef AEE_SIMULATOR // only if not in the SDK, resend the event
if(pMe->keyIsPressed)
{
/*
If the event handler below returns FALSE, it simply
means that the event handler doesn't handle EVT_KEY_PRESS
for the key the user is holding down. No action needed in
this case, because as soon as the user releases the key,
the EVT_KEY_RELEASE is sent and pMe->keyIsPressed becomes FALSE.
*/
PFN_EVENTHANDLER eventHandlerFunc = GetEventHandler(pMe->state);
if(eventHandlerFunc)
{
eventHandlerFunc(pMe, EVT_KEY_PRESS, pMe->lastKeyPresswParam,
pMe->lastKeyPressdwParam);
}
else
{
DBGPRINTF("Error getting event handler");
}
}
#endif
/*
At this point in the code, we've drawn the completed frame to the screen.
We're ready to restart the rendering loop for the next frame, taking any
changes due to key events into account. We restart the rendering loop by
setting a timer which will call a drawing routine in a given amount of
time. We can't call the draw routine here directly. This is because
the draw routine calls I3D_StartFrame(), which in turn will return us to
the event notifier we're currently in. So to avoid this never ending
recursion, we set a timer to call the draw routine, giving control back to
BREW in the meantime.
By adjusting CALLBACK_TIME, one can set a particular frame rate for
the I3D application. Setting CALLBACK_TIME to 0 will simulate a direct call
to the respective draw function.
*/
// only set the timer if the state we're going to needs to do rendering
if(isRenderState(pMe->state) )
{
int ret;
if(pMe->drawModel == MODEL_CUBE)
{
CALLBACK_Init(&pMe->cb, (PFNNOTIFY)TutorI3D_DrawCube, (void *) pMe);
ret = ISHELL_SetTimerEx(pMe->a.m_pIShell, CALLBACK_TIME, &pMe->cb);
}
else if(pMe->drawModel == MODEL_SPHERE)
{
CALLBACK_Init(&pMe->cb, (PFNNOTIFY)TutorI3D_DrawSphere, (void *) pMe);
ret = ISHELL_SetTimerEx(pMe->a.m_pIShell, CALLBACK_TIME, &pMe->cb);
}
else if(pMe->drawModel == MODEL_SMOOTH_SPHERE)
{
CALLBACK_Init(&pMe->cb, (PFNNOTIFY)TutorI3D_DrawSmoothSphere, (void *) pMe);
ret = ISHELL_SetTimerEx(pMe->a.m_pIShell, CALLBACK_TIME, &pMe->cb);
}
else if(pMe->drawModel == MODEL_FIELD)
{
CALLBACK_Init(&pMe->cb, (PFNNOTIFY)TutorI3D_DrawField, (void *) pMe);
ret = ISHELL_SetTimerEx(pMe->a.m_pIShell, CALLBACK_TIME, &pMe->cb);
}
else
{
CALLBACK_Init(&pMe->cb, (PFNNOTIFY)TutorI3D_DrawLadyBug, (void *) pMe);
ret = ISHELL_SetTimerEx(pMe->a.m_pIShell, CALLBACK_TIME, &pMe->cb);
}
// check error codes
if(ret == ENOMEMORY)
{
DBGPRINTF("Error: Ran out of memory setting timer");
}
else if(ret == EINVALIDTIME)
{
DBGPRINTF("Error: Invalid time for timer");
}
else if(ret != SUCCESS)
{
DBGPRINTF("Error: Couldn't set timer");
}
}
break;
default:
return;
}
}
/*===========================================================================
FUNCTION TutorI3D_HandleEvent
DESCRIPTION
This is the EventHandler for this app. All events to this app are handled in this
function. All APPs must supply an Event Handler.
PROTOTYPE:
boolean TutorI3D_HandleEvent(IApplet * pi, AEEEvent eCode, uint16 wParam, uint32 dwParam)
PARAMETERS:
pi [In]: Pointer to the AEEApplet structure. This structure contains information specific
to this applet. It was initialized during the AEEClsCreateInstance() function.
ecode [In]: Specifies the Event sent to this applet
wParam, dwParam [In]: Event specific data.
DEPENDENCIES
none
RETURN VALUE
TRUE: If the app has processed the event
FALSE: If the app did not process the event
SIDE EFFECTS
none
===========================================================================*/
boolean TutorI3D_HandleEvent(IApplet * pi, AEEEvent eCode, uint16 wParam, uint32 dwParam)
{
TutorI3D* pMe = (TutorI3D*) pi;
// get the event handler for the given state.
PFN_EVENTHANDLER eventHandlerFunc = GetEventHandler(pMe->state);
DBGPRINTF("Event: %d, wParam: %d", eCode, wParam);
switch (eCode)
{
/*
EVT_APP_START is sent to the application to indicate that it should
initialize itself and begin executing
*/
case EVT_APP_START:
if(TutorI3D_DrawIntroScreen(pMe) == FALSE)
DBGPRINTF("Error: Can't draw intro screen");
// allocate needed variables, interfaces, models, etc.
if(TutorI3DInit(pMe) == FALSE)
return FALSE;
// set the application defaults
if(TutorI3D_SetDefaults(pMe) == FALSE)
return FALSE;
// prepare main menu
if(TutorI3D_InitMainMenu(pMe) == FALSE)
return FALSE;
// All incoming BREW events come through the main event
// handler. Based on the state variable, the events are sent
// to the appropriate event handler. Here we're going to the main state.
pMe->state = STATE_MAIN;
// draw the main menu
if(TutorI3D_DrawMainMenu(pMe) == FALSE)
return FALSE;
return(TRUE);
/*
EVT_KEY_PRESS is sent once when a key is pressed. EVT_KEY_PRESS events will
be followed by EVT_KEY_RELEASE events (not necessarily consecutively).
In this manner, we can tell if a key is being held down and take the
appropriate action if it is. Keys that are used for repeated
action while being held down, should use EVT_KEY_PRESS and EVT_KEY_RELEASE.
Keys that only take action once even while being held down should use
the EVT_KEY events, which are also sent once when a key is pressed.
NOTE: In the SDK, EVT_KEY_PRESS and EVT_KEY are repeatedly sent while a
key is held down. This is not the case on target, they are sent once
per key press, even if the key is held down. This is the reason why on
target you have to use EVT_KEY_PRESS and EVT_KEY_RELEASE to check
if a key is held down, and take the appropriate action.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -