⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tutori3d.c

📁 用brew开发3D的例程
💻 C
📖 第 1 页 / 共 5 页
字号:

	// 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 + -