牛顿引擎教程翻译

来源:互联网 发布:json怎么解析 编辑:程序博客网 时间:2024/06/04 19:17

Downloadthe fileNewtonTutorial.zip from the Newton website and unpack itanywhere in your windows machine, if you have not done so.

从网站下载并解压NewtonTutorial.zip到任何你想要放置的位置。

Thesetutorials are made for Win32, compiled with visual Studio 2003 andusing Simple DirectMedia Layer (SDL)for Graphics, Sound and Input. All of the elements in the tutorialsare cross platform, therefore it should be simple to build then onother platform like win64, Linux, and Mac OS. However this is a basictutorial and we will not experiment with that right now.

这部分案例为win32平台制作,使用vs2003编译,使用SDL处理图像、声音和输入。案例中所有的元素都是跨平台的,所以可以很容易的在其他平台创建,例如win64linuxMacOS

Afterunpacking, go to the folder .../NewtonToturials and open the visualstudio solution NewtonTutorials.sln

解压完成后到NewtonToturials文件夹下,打开NewtonTutorials.sln

Inthe solution explorer right click on projectTutorial_101_GettingStarted and select Set as Startup Project, thenclick Rebuild Solution. All the dependencies are included in thedownload; therefore all projects should build with zero warning andzero errors.

设置Tutorial_101_GettingStarted为项目启动工程。重建(Rebuild)项目,所有的依赖项都在下载文件中;因此所有的工程应该被正常的建立。

Openup file Main.cpp

Thefirst lines of code

#include<stdafx.h>

#include<dVector.h>

#include"OpenGlUtil.h"

#include"CreateScene.h"


#defineUSE_VISUAL_DEBUGGER

#defineDEMO_FPS_IN_MICROSECUNDS (int (1000000.0f/100.0f))


staticint g_currentTime;

staticint g_physicTime;

staticint g_timeAccumulator = DEMO_FPS_IN_MICROSECUNDS;


staticvoid* g_newtonDebugger;

staticNewtonWorld* g_world;

staticSceneManager* g_sceneManager;


staticvoid ShutDown ();

staticvoid* AllocMemory (int sizeInBytes);

staticvoid FreeMemory (void *ptr, int sizeInBytes);

staticvoid AdvanceSimulation (int timeInMilisecunds);


#pragmawarning (disable: 4100) //unreferenced formal parameter

#pragmawarning (disable: 4702) //unreachable code

Arejust the necessary included files, constant and variables necessaryfor the project to work.

以上代码包含了必要的库文件,常量和变量以保证工程正常运行。

Thefirst Line in function main

_CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF|_CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF));

Isa operating system memory leak check handler that indicates if somememory allocation was not freed on exit.

函数mian()第一行代码是操作系统内存泄露检测函数,用来指出是否有分配的内存在退出后没被释放。

Thefollowing lines:

//initialize graphics system

if(!InitGraphicsSystem (800, 600)) {

exit(0);

}

Initializesa proper SDL Graphic System that will be use to visualize the physicsscene. You are welcome to step into the function in debug mode to seehow it is implemented, I will not spend time explaining the details,I will only say the code was taken almost verbatim from the SDLexamples.

初始化SDL图形处理系统,用来显示物理场景。你可以进入调试模式了解它如何执行。这里不会花时间解释太多细节。

Next

//set a callback for destroying the world at termination

atexit(ShutDown);

Atermination function is set, which will be called when the userdecides to terminate the program. For most Graphics engines with agracious ways to shutting down this is not necessary, but graphicslibraries like SDL and GLUT do not terminate with grace and alltermination code has to be added during forced exit termination. Thetermination function looks like this:

一个程序结束的设置,将会在程序结束时被调用。多数图形引擎不需要这么做,但是SDLGLUT引擎结束时,结束代码必须被加入。结束函数如下:

//On termination, the application must destroy the Newton world

voidShutDown ()

{

#ifdefUSE_VISUAL_DEBUGGER

//destroy the debugger server

NewtonDebuggerDestroyServer(g_newtonDebugger);

#endif


//destroy all rigid bodies, this is not necessary because NewtonDestroy world will also destroy all bodies

//but if you want to change level and restart you can call thisfunction.

NewtonDestroyAllBodies(g_world);


//finally destroy the newton world

NewtonDestroy(g_world);


//now we need to destroy the Graphics entities

Deleteg_sceneManager;

}

Essentiallythis destroys all objects created by the application in reverseorder.

本质上,这个函数依照倒序卸载所有的被程序创建的物体。



Next

<prev>

//now populate the world with Graphic and physical entities

CreateScene(g_world,g_sceneManager);

</prev>

EveryGraphics engine has a way to encapsulate the various graphicscomponents of a visual object into some kind of structure, in thistutorials will call those object Entities.

所有的图形引擎都会把可视化对象的各种图形组件封装成某种特定的结构,在这些案例中我们称这些组件为Entitie(实体)。

Inturns these Entities are encapsulated into an even higher levelobject called Scene Manager. A Scene Manager is an object thatencapsulates most of the functionality of graphics engine.

对象Entities被封装到更高级别的(称之为场景管理器SceneManager)对象中,场景管理器是封装了大量图形引擎函数的对象。

Itmanages the creation, destruction, user interface and motion of anygraphic object. For the purposes of these tutorials the scene manageris a class that looks like this:

场景管理器负责建立、销毁、控制所有的图形对象。它是一个类,形式如下:

<prev>

classSceneManager

{

public:

SceneManager(void);

virtual~SceneManager(void);


voidCreateScene();

Entity*CreateEntity();


voidSetIntepalationParam(dFloatparam);

voidRender();


protected:

intm_entCount;

dFloatm_intepolationParam;

Entity*m_entityArray[MAX_ENTITY_COUNT];

};

</prev>

Basicallyis a very simple flat array of Entities.

基本上就是一个简单的数组entities

Thefollowing lines, initializes the default settings for a Newton world

下面的代码用默认的设置初始化世界。

//create the Newton World

g_world= NewtonCreate (AllocMemory, FreeMemory);


//configure the Newton world to use iterative solve mode 0

//this is the most efficient but the less accurate mode

NewtonSetSolverModel(g_world, 1);


//use the standard x87 floating point model

NewtonSetPlatformArchitecture(g_world, 0);


//set a fix world size

dVectorminSize (-500.0f, -500.0f, -500.0f);

dVectormaxSize ( 500.0f, 500.0f, 500.0f);

NewtonSetWorldSize(g_world, &minSize[0], &maxSize[0]);

Thefunction NewtonCreate passes the pointer to memory allocationfunctions that will take care of all the engine memory allocation.These functions are optional, you can pass NULL but you cannot passone or the other, if you decided to control memory allocation thenyou must write a memory allocation and a memory free function. At thesimplest level these function should look like this:

函数NewtonCreate()传递内存分配函数的指针。内存分配函数是可选的,你可以传递NULL但不能传递one或其它值。如果你想控制内存位置,那么就必须写一个内存分配和内存回收函数。最简单的函数如下:

//this is the callback for allocating Newton memory

void*AllocMemory (int sizeInBytes)

{

returnmalloc (sizeInBytes);

}


//this is the callback for freeing Newton Memory

voidFreeMemory (void *ptr, int sizeInBytes)

{

free(ptr);

}


Thefollowing lines show a new feature in SDK 2.00

下面的代码展示SDK2.00的新功能

//initialize Newton Visual Debugger

#ifdefUSE_VISUAL_DEBUGGER

g_newtonDebugger= NewtonDebuggerCreateServer ();

#endif

Itis the visual debugger, at the time of the writing these tutorial theVisual Debugger Listener is not yet fully implemented.

可视化调试管理,写此教程之前此功能还不能被完全的执行。



Next

//now populate the world with Graphic and physical entities

CreateScene(g_world, g_sceneManager);



Forthese tutorials the Entity class looks like this:

entity如下所示:

classEntity

{

public:

structSubMesh

{

unsignedm_textureHandle;

intm_indexCount;

unsignedshort* m_indexArray;

};


Entity(void);

virtual~Entity(void);


voidLoadMesh (const char* name);

virtualvoid Render (dFloat interpolationParam);


//these are the element to represent the position and orientation stateof a graphics object in the world

dMatrixm_matrix; // current interpolated visual matrix

dVectorm_curPosition; // position one physics simulation step in thefuture

dVectorm_prevPosition; // position at the current physicssimulation step

dQuaternionm_curRotation; // rotation one physics simulation step inthe future

dQuaternionm_prevRotation; // rotation at the current physics simulationstep



//These are the elements for a simple vertex list index list graphicsobject.

intm_subMeshCount;

intm_vertexCount;

dFloat*m_uv;

dFloat*m_vertex;

dFloat*m_normal;

SubMesh*m_subMeshes;

};

Thisclass in not part of Newton and it is not part of any Graphicsengine, It is just an easy way to group graphics functionality inthis tutorial, please do not use this class as part of the physicsengine.

这个类不属于牛顿引擎以及其它任何图形引擎,它只是个简单的组织图形处理函数的方式,请不要在物理引擎中使用这个类。

Thisis where the application will create and save all graphics scene,

Forthis simple tutorial we create a simple scene with a big box as floorand two other small boxes floating on the air.

这里就是程序建立和存储图形场景的地方,这个示例教程里我们建立了一个简单场景,这个场景包含一个用来做地面的大盒子,以及另外两个悬浮在空中的小盒子。

<prev>

voidCreateScene(NewtonWorld*world,SceneManager*sceneManager)

{

Entity*floor;

Entity*smilly;

Entity*frowny;


//Create a large body to be the floor

floor=sceneManager->CreateEntity();

floor->LoadMesh("FloorBox.dat");


//add some visual entities.

smilly=sceneManager->CreateEntity();

smilly->LoadMesh("Smilly.dat");

smilly->m_curPosition.m_y= 10.0f;

smilly->m_prevPosition=smilly->m_curPosition;


//add some visual entities.

frowny=sceneManager->CreateEntity();

frowny->LoadMesh("Frowny.dat");

frowny->m_curPosition.m_x= 0.5f;

frowny->m_curPosition.m_z= 0.4f;

frowny->m_curPosition.m_y= 10.0f;

frowny->m_prevPosition=frowny->m_curPosition;

}

</prev>




Subsequencestutorials will go straight to this function to explain the process ofadding physics properties to the graphics scene.

后面的教程将继续解释增加物理属性到图形场景的处理方法。





Nextwe add the application main loop.

接下来我们增加程序主循环。

//run the main application loop until the user terminates the demo

for(;;) {

//Draw the screen.

AdvanceSimulation(GetTimeInMicrosenconds ());

}

Thisis the simplex main simulation loop we can come up with, it advancesthe Physical and Graphical simulation by calling AdvanceSimulationwith a time elapsed since the last loop in microseconds.

这是我们提出的一个简单的模拟主循环,他通过函数AdvanceSimulation()执行物理和图形模拟。

Ifyou lock at function AdvanceSimulation, you will find that thisfunction has two parts.

Firstparts updates physical simulation at a fix time step and collect theexternal inputs to the application. It also calls the Visual debuggerto visualize the Physical Scene on the external Visual debugger.

如果看一下函数AdvanceSimulation(),你会发现这个函数由两部分组成。

第一部分以固定的时间节奏更新物理模拟以及收集外部的输入。他调用Visualdebugger()来显示物理场景的调试信息。

intdeltaTime;

dFloatfps;

dFloatphysicTime;

dFloatinterpolationParam;

//get the time step

deltaTime= timeInMilisecunds - g_currentTime;

g_currentTime= timeInMilisecunds;

g_timeAccumulator+= deltaTime;

physicTime= 0;

//advance the simulation at a fixed time-step

while(g_timeAccumulator >= DEMO_FPS_IN_MICROSECUNDS)

{

//sample time before the Update

g_physicTime= GetTimeInMicrosenconds ();


//do a newton update

NewtonUpdate(g_world, dFloat (DEMO_FPS_IN_MICROSECUNDS) * 1000000);


//calculate the time spent in the physical Simulation

g_physicTime= GetTimeInMicrosenconds () - g_physicTime;


//Process incoming events.

ProcessEvents();


//call the visual debugger to show the physics scene

#ifdefUSE_VISUAL_DEBUGGER

NewtonDebuggerServe(g_newtonDebugger, g_world);

#endif


//subtract time from time accumulator

g_timeAccumulator-= DEMO_FPS_IN_MICROSECUNDS;

physicTime++;

}


Basicallythis is a loop designed to run the physics update at a fixedtime-step. It keeps track of the delta time accumulated since thelast call, and every time the accumulated time is equal or larger toone physical time step, represented by constDEMO_FPS_IN_MICROSECUNDS, the loop issues a call to a ProcessEvent,NewtonUpdate, NewtonDebuggerServe and the time step is subtractedfrom the time accumulator.

基本上,这个循环的作用是在一个固定的时间节拍下执行物理模拟更新。他在下一个调用之前保持时间片的积累,当累积时间大于或等于一个时间节奏(physicaltime step),定义为一个常量DEMO_FPS_IN_MICROSECUNDS,则这个循环会调用ProcessEventNewtonUpdateNewtonDebuggerServe,并重置时间节拍。

ProcessEventis the function in charge of collecting the user inputs forcontrolling the simulation. NewtonUpdate is the Newton Engine mainupdate functions, and is does all of the physical work on all physicsentities. NewtonDebuggerServe displays the physical state of theworld to the external visual debugger.

函数ProcessEvent()用来收集用户输入。函数NewtonUpdate()是牛顿引擎的核心更新函数,它处理所有的物理实体的模拟工作。函数NewtonDebuggerServe显示世界的物理状态。

Thesecond part on this function updates the Camera, Render the GraphicsScene and display some useful information on the screen.

第二部分更新摄像机,渲染图形场景以及在屏幕上显示一些有用的信息。

<prev>

//Clear the color and depth buffers.

glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);


//calculate the interpolation parameter for smooth rendering

g_sceneManager->SetIntepolationParam(dFloat(g_timeAccumulator)/dFloat(DEMO_FPS_IN_MICROSECUNDS));


//do the rendering here entire Scene

g_sceneManager->Render();


//display the frame rate

fps= 1000000.0f / dFloat(deltaTime);

physicTime=g_physicTime*dFloat(1.0f/ 1000000.0f);

Print(dVector(1.0f, 1.0f, 0.0f, 0.0f), 10, 10, "fps: %6.2f physic time(milliseconds): %6.2f", fps,physicTime);


//show GL rendered Scene

glFlush();

SDL_GL_SwapBuffers();

</prev>

Herethe most important part is that the rendering does not happen at thesame rate than the physics, because of this, the rendering systemmaintains two transformation states: the old state and the state oneafter DEMO_FPS_IN_MICROSECUNDS has passed. The graphics system willcalculate the correct transformation for visualization byinterpolating the fraction of time elapsed between the two stages.The fraction of elapsed time is calculated in a variableinterpolationParam

这里提到最重要的一点,渲染和物理模拟不是同一个速率执行的,所以,渲染系统维护两个转换状态;原始状态(oldstate)和经过一个时间节奏后的状态。图形引擎会通过逝去时间差值计算当前的转换状态。逝去时间存储在变量interpolationParam中。

<prev>

//calculate the interpolation parameter for smooth rendering

g_sceneManager->SetIntepolationParam(dFloat(g_timeAccumulator)/dFloat(DEMO_FPS_IN_MICROSECUNDS));

</prev>



Thisends this tutorial. We have created a Graphics framework that willserve as our representation of the minimum functionality of mustgraphics engines.

Weintegrated the Newton Engine in this hypothetical graphics engine,and believe it or not it is this simple to integrate Newton in to agraphics engine.

Nexttutorials will demonstrate how to add Physical properties to each ofthe entities in of the graphics world.

至此,我们建立了一个图形框架来当做一个最轻量级的基础图形引擎。

我们将牛顿引擎集成到这个基础的图形引擎里。这就是集成牛顿引擎的简单实例。



原创粉丝点击