follow my heart...
分类:
2006-11-26 19:16:37
//After compilation, this source code is turned into a file named 3impactd.dll and
//saved to the 3impactWork folder on your hard disk.
//When 3impactd.exe file (the engine) is launched, it will load this .dll file and
//will execute the five functions below, also known as 'callbacks'.
//They are: PreInit(), Init(), Run(), Exit(), PostExit().
//You can fully control the engine by calling creation functions, setting functions
//and transformation functions inside the callbacks. It is that easy! See below.
//Include some external code giving access to commonly used Windows methods
#i nclude
#i nclude
#i nclude
//Include also some engine specific functions and definitions.
#i nclude "..\common\3impactDLL_defs.h"
//In the Init() callback you'll see that we create virtual world objects by calling
//creation functions.
//Newly created objects should always be stored to proper 'containers', named
//'object variables', to allow for subsequent handling.
//Object variables are typically declared at the beginning of the code. Typically, one
//single line of code declares one single variable. A declaration is made of two parts.
//The first part declares the type of the variable (for example 'CAMERA*') and the
//second part declares its custom (user defined) name (for example 'Camera').
//For simplicity, an object variable is usually called 'object' (e.g., 'camera object').
//The following are the object variables we need for this example.
CAMERA* Camera;//摄像机
SPRITE* LoadingMessage;//加载信息
SKYBOX* SkyBox;//天空
BODY* Terrain;//地形
MESH* TerrainMesh;//地形模型
BODY* Ball;//球
MESH* BallMesh;//球模型
MESH* BallMeshShadow;//球阴影
BODYBODY* BallTerrain;//球与地形之间
void PreInit(DWORD* settings)//预初始化,产生在显示对话框之前
{
//This callback is executed once, at startup, before opening the Display Options panel.
//Note that 3Impact functions are not available here yet. You cannot call, for
//example, iCameraCreate(). This callback is intended for special initializations.
//We don't need any special initialization now, so we are leaving this callback empty.
}
void Init()//初始化
{
//This callback is executed once, right after opening the rendering window or the
//rendering fullscreen display.
//This callback is typically used to create objects, to set their initial status,
//physics properties, rendering mode, etc.
//We always need to create a camera (point of view). Without a camera, nothing can
//be rendered to the screen. The following line calls the iCameraCreate() function
//and stores the camera object which it creates to the object variable named Camera.
Camera=iCameraCreate(0,0,100,100);//创建摄像机
//Now that the newly created camera is in the 'Camera' variable, we can handle it.
//For example, we can set its location, inside the virtual space. The next line of code
//calls the iCameraLocationSet() function, passing the Camera as first parameter and
//a constant 3d vector as second parameter (the location).
iCameraLocationSet(Camera,&D3DXVECTOR3(0.0f,3.0f,-10.0f));//设置摄像机位置
//We also want to specify sun light direction and color.
//设置光线方向与色彩
iLightDirectionalSet(&D3DXVECTOR3(1.0f,-1.0f,1.0f),&D3DXVECTOR4(1.0f,1.0f,1.0f,0.35f));
//Creating objects can be a lengthy operation. We want to display something while
//loading is in progress. So we create a 2d object (also known as 'sprite') to
//display a 'Loading...' message.
//Note that object creation will typically require a resource file, as source.
//For example, for sprites, we need an image file and a .x file.
//Custom resources can be created. Refer to the quick start tutorial for details.
//The next line of code will create a sprite from the loading.x resource, and will
//store it to the variable named 'LoadingMessage'.
//创建加载精灵
LoadingMessage=iSpriteCreate("default_res\\sprites\\loading.x",NULL);
//We want the message displayed now, before we start creating (loading) all other objects.
//渲染精灵,以便显示
iSpriteRender(LoadingMessage,NULL);
//We now create a 3d background for the virtual space.
//为虚拟空间创建一个3d背景
SkyBox=iSkyBoxCreate("default_res\\skyboxes\\skybox01.sky");
//The first 3d 'solid' object we create is a piece of terrain. Solid objects
//are called 'bodies'. A body is considered 'solid' because it is collision-response
//capable. In this case, the body is a polygonal object (polyhedron).
//创建地形实体 ,但是实体是无法显示的 ,注意地形实体是基于多面体的 ,所以扩展名是ply
Terrain=iBodyCreate("default_res\\terrain_5.00.ply");
//Bodies are invisible. They are processed by the engine as invisible-solid objects.
//It means that they cannot be rendered (displayed) by the engine. However, we can
//attach a visible mesh to them, to show where they are and what their shape is.
//Mesh objects are non-solid 3d models. Unlike bodies, they are rendered by the engine.
//With the next line of code, we create a 3d visible object from a .x
//resource file. As parameters, we pass the file name for the resource to load and
//the body object we want attach the mesh to (Terrain).
//创建地形模型,依附于地形实体
TerrainMesh=iBodyMeshCreate("default_res\\terrain.x",Terrain);
//The second body we create is a ball. Unlike the terrain, which is made of polygons,
//this object is sphere-group based. It is as simple as a ball, so it is a one-ball
//group. See quick start tutorial for details on polyhedron and sphere-group based bodies.
//基于球体创建,注意扩展名是spg(sphere-group)
Ball=iBodySGCreate("default_res\\ball_.spg",0.13f);
//As a body, the newly created ball is invisible. Let's attach a ball-shaped mesh to it.
//依附于球体创建球模型
BallMesh=iBodyMeshCreate("default_res\\ball.x",Ball);
//We want the ball at about 5 meters above the ground, at startup.
//设置球体位置处于离地面5m
iBodyLocationSet(Ball,&D3DXVECTOR3(0.0f,5.0f,0.0f),TRUE);
//By default, there is no air friction for bodies. We can simulate it by setting
//some damping for the ball.
//See reference.txt for details on iBodyDampingSet() instruction and damping.
//设置实体阻碍
iBodyDampingSet(Ball,0.0f,0.999f,0.0f,0.995f);
//We want our ball to cast a shadow onto other objects in the scenery.
//The next line of code creates a shadow volume mesh from a source .x file
//and attaches it to the Ball body. See reference.txt for details on
//iMeshBodyShadowCasterCreate() instruction and shadows.
//创建球的阴影
BallMeshShadow=iMeshBodyShadowCasterCreate("default_res\\ball_shadow.x",Ball,500.0f);
//By default, no collision checking is performed for the bodies we have created.
//We have to tell the engine what body couples should be checked for collision.
//The next line of code creates a so called body-body object.
//Basically, the body-body object is a data block specifying a body couple and
//a few parameters required by the engine to compute collision-response.
//创建球与地面一对物体
BallTerrain=iBodyBodyCreate(Ball,Terrain);
//We have stored the body-body object for the ball-terrain couple, so that we can
//set collision-response parameters for it. See reference.txt for details on them.
//物体之间摩擦力设置
iBodyBodyFrictionSet(BallTerrain,10.0f);
//Newly created bodies are disabled (no physics, no collision-response computation).
//The next two lines of code enable Ball and Terrain bodies.
//使地形可用
iBodyEnable(Terrain);
//使球体可用
iBodyEnable(Ball);
//We don't want to show the loading message any longer, now that object creation is complete.
//到此为止,加载工作完成,隐藏loading信息
iSpriteHide(LoadingMessage);
//Newly created meshes are hide. Let's show all of them.
//显示天空,地形模型,球模型及球阴影模型
iSkyBoxShow(SkyBox);
iMeshShow(TerrainMesh);
iMeshShow(BallMesh);
iMeshShow(BallMeshShadow);
}
//运行的循环过程
void Run()
{
//This callback is executed 75 times per second. The first execution happens
//after the Init() callback above is completed.
//It means that the engine will repeatedly scan the lines of code from the '{'
//right below the 'void Run()' line to the '}' right above the 'void Exit()' line.
//Each scan from '{' to '}' is called 'dll loop'. It is basically the heartbeat
//of the simulation.
//The rendering phase, in which the virtual world is displayed in its current status,
//as seen from the current camera location, happens after each dll loop is complete.
//The dll loops continue until the [Esc] key is pressed or the iExit() function
//is called. Terminating the dll loops basically stops the simulation.
//So, we have a piece of terrain and a ball. We want the camera to constantly
//take the ball, wherever it goes. First of all, let's define a vector variable
//to save the current ball position, that is the target to point the camera to.
//定义一个矢量变量保存球的位置,同样这位位置也是摄像机的点
D3DXVECTOR3 cameratarget;
//We put the current ball location into the vector by calling iBodyLocationCM().
//
iBodyLocationCM(Ball,&cameratarget);
//Finally, we call a special function that will point the camera to the target.
//指定摄像机到目标上面
iCameraLookAt(Camera,&cameratarget,0.1f);
//We finally want the ball to be controlled by key presses. The idea is applying
//forces to it according to what arrow keys are pressed by the user.
//First of all, let's define proper variables to store some temporary information
//we need to achieve our goal.
//加速点
D3DXVECTOR3 acceleration;
//四元组- 摄像机方向
D3DXQUATERNION cameraorientation;
//Linear accelerations (*) are defined by 3d vectors. We have provided a variable
//named 'acceleration' to store the acceleration generated by key presses.
//This vector variable will work as an accumulator. The first step is resetting it.
//给加速点赋值
acceleration=D3DXVECTOR3(0.0f,0.0f,0.0f);
//Depending on what keys are pressed, we will add a constant vector to the
//acceleration variable. The length of the vector defines the intensity of
//the acceleration. The direction of the vector defines the direction of it.
//For example, if up-arrow is pressed, we add a 10 meter long vector
//to the accumulator. Its direction is towards Z-positive world axis.
//It basically means that the ball will be pushed with an acceleration of 10
//meters per second^2 in that direction, when up-arrow is pressed (**).
//通过箭头键来控制加速方式
if (iKeyDown(DIK_LEFT)) acceleration += D3DXVECTOR3(-10.0f,0.0f,0.0f);
if (iKeyDown(DIK_RIGHT)) acceleration += D3DXVECTOR3(10.0f,0.0f,0.0f);
if (iKeyDown(DIK_UP)) acceleration += D3DXVECTOR3(0.0f,0.0f,10.0f);
if (iKeyDown(DIK_DOWN)) acceleration += D3DXVECTOR3(0.0f,0.0f,-10.0f);
//(**) The code above basically tends to push the ball along world's X and Z
//axes only, no matter where the camera is taking the scene from. It makes a bit
//difficult for the user to effectively direct the ball.
//We want to re-orientate the resulting acceleration vectors so that they
//are camera relative. For example, we want an acceleration towards X+ axis to be
//re-orientated so that it becomes an acceleration towards the right of the screen.
//To achieve this, we first store the camera orientation to a quaternion variable.
//Note: most physics engine quantities (locations, forces, torques, etc) can be stored
//to vector variables. To store orientations and rotations we use special variables
//called 'quaternions'.
//设置摄像机方向
iCameraOrientation(Camera,&cameraorientation);
//The next function takes a vector (acceleration) and rotates it by using a
//quaternion as a reference. Basically, 'cameraorientation' quaternion is
//the rotation required to change the camera from its natural status (that
//is, looking at Z+ horizon) to its current orientation. We can
//say that it is the current camera orientation, but it is a rotation actually.
//So, we basically apply that orientation to the given vector. The result
//is that the vector is transformed from world coordinates (absolute) to
//camera coordinates (relative). And it is exactly what we need here.
//矢量旋转
iVectorRotate(&acceleration,&acceleration,&cameraorientation);
//Controls are easier now that applied acceleration has been made camera-relative.
//Still we aren't done yet. Controlling the ball when the camera is pitched (for
//example facing downward) isn't very easy. For some reason, it would be easier
//if acceleration vector direction was always parallel to the XZ (ground) plane.
//To constrain the vector to the XZ plane we just have to force its Y
//coordinate to zero. Note that this may reduce vector length (intensity) on
//extreme camera pitching, but it is ok for this simple example.
acceleration.y = 0.0f;//设置y轴,也就是高度为0
//在坐标系中,X是水平移动,Y是高度,Z是纵深
//Now that the acceleration vector is set (or still reset to null if no
//key was pressed), we can finally apply it to the Ball body.
//(*) We are applying an acceleration and not a force. Applying a force
//means transferring to a body a defined quantity of energy. So, the resulting
//speed depends on the body mass: a force applied to an heavy body will generate
//a lower speed respect to the same force applied to a lighter body.
//Applying an acceleration, instead, means transferring to a body the energy required
//to obtain, over time, a defined velocity or spin, regardless of the body mass.
//应用加速-球
iBodyAccelerationApply(Ball,&acceleration);
//Finally, we apply a constant acceleration to simulate gravity.
//We also implement an additional control, with the next lines of code.
//We want to reverse the gravity force (but we should actually name it
//'gravity acceleration'...) while the [Ctrl] key is pressed.
//当按下ctrl键时,球在Y轴上升,相反如果没有按的话,球下降.
if (!iKeyDown(DIK_LCONTROL)) iBodyAccelerationApply(Ball,&D3DXVECTOR3(0.0f,-9.80665f,0.0f));
else iBodyAccelerationApply(Ball,&D3DXVECTOR3(0.0f,9.80665f,0.0f));
}
//退出
void Exit()
{
//This callback is executed after the Run() callback is stopped by pressing [Esc],
//before the rendering window is closed.
//You typically free any memory resource you have allocated elsewhere, here.
}
//发送退出
void PostExit(HWND hWnd)
{
//This callback is executed after the Exit() callback, after closing the
//rendering window, before closing the application.
//It is intended for special purposes like, for example, running an external
//application, an Internet browser, etc.
}