编程
Fundamentals
Setting Up Development Environment
UnigineScript
High-Level Systems
C++
C#
UUSL (Unified UNIGINE Shader Language)
File Formats
Rebuilding the Engine and Tools
GUI
Double Precision Coordinates
应用程序接口
Containers
Common Functionality
Controls-Related Classes
Engine-Related Classes
Filesystem Functionality
GUI-Related Classes
Math Functionality
Node-Related Classes
Networking Functionality
Pathfinding-Related Classes
Physics-Related Classes
Plugins-Related Classes
Rendering-Related Classes

基本的对象运动

待您将对象添加给Unigine之后,就可以通过外部控制设备来控制其变换了。 本文向您展示了如何控制基本的对象运动,如何组合不同的变换。

注意
在下面的例子中,我们使用了路径<UNIGINE SDK>/data/samples/common/meshes/下的statue.mesh网格。

另请参阅

方向向量

方向向量是mesh变换的重要概念。 要想向前移动节点,就须知晓mesh的前进方向在哪。 当mesh被从3D设计软件导出时,它是保存有与前进方向有关的信息的。 在您将mesh添加给了Unigine时,其朝向将与它在3D设计软件中的朝向一致。

Maya中的mesh
相同的mesh在Unigine

上述两幅图中,方向向量都拥有正的Y方向。 要想向前移动这个mesh,就须通过网格的世界变换矩阵的Y分量(指矩阵的第二列)来获取该mesh的方向。

例如,在City Traffic(城市交通)项目中,方向向量拥有正的Y方向。 要想将新的car添加给City Traffic(要将所有逻辑应用给已添加的car),那它从3D设计软件导出时就应带有指定的方向向量。

需要指出的是,内容创建者和程序员应就方向向量问题进行协商。

基本运动

向前移动

这部分包含了设置mesh前向移动的不同方式。

在本例中,我们使用了按"p"键向前移动mesh的方法。

源代码 (UnigineScript)
// 定义ObjectMeshStatic网格和移动速度
ObjectMeshStatic mesh;
float movement_speed = 5.0f;

// 初始化自定义控制(controls)
void init_controls() {

	// 检测按键是否被按下以及更新指定control的状态
	// 您可以使用'p',也可以使用ASCII码(112)
	engine.controls.setStateKey(CONTROLS_STATE_AUX_0,'p');
}

// 将mesh作为节点添加给Editor
Node add_editor(Node node) {
	engine.editor.addNode(node);
	return node_remove(node);
}

/* world(世界)脚本的init()功能
 */
int init() {
	/* 创建一摄像机并将其添加给虚拟世界
	 */
	Player player = new PlayerSpectator();
	player.setDirection(Vec3(0.755f,-1.0f,0.25f));
	engine.game.setPlayer(player);
	
	// 将mesh添加给虚拟世界并设置材质
	mesh = add_editor(new ObjectMeshStatic("unigine_project/meshes/statue.mesh"));
	mesh.setMaterial("mesh_base", "*");

	// 调用init_controls()函数
	init_controls();

	return 1;
}

/* world(世界)脚本的update()功能
*/
int update() {

	// 获取帧时长
	float ifps = engine.game.getIFps();

	// 检查控制键是否被按下
	if(engine.controls.getState(CONTROLS_STATE_AUX_0)) {

		// 获取mesh的当前世界变换矩阵
		Mat4 transform = mesh.getWorldTransform();

		// 获取mesh的方向向量
		Vec3 direction = transform.m00m10m20;

		// 计算移动的增量
		Vec3 delta_movement = direction * movement_speed * ifps;

		// 为mesh设置新位置
		mesh.setWorldPosition(mesh.getWorldPosition() + delta_movement);
	}

	return 1;
}

另一种获取方向向量的方法是通过如下命令:

源代码 (UnigineScript)
Vec3 direction = Vec3(transform.col0);

这行代码显然更具可读性,不过却需要对Vec3进行附加的强制类型转换。

设置网格位置的其它方法

也可通过setWorldTransform()函数设置新位置。 下面的几个例子都包含了取自world(世界)脚本的update功能代码。 对这一方法而言,控制(controls)的初始化部分都是相同的,不同之处是world(世界)脚本的update()功能内部。

源代码 (UnigineScript)
// 检查控制键是否被按下
if(engine.controls.getState(CONTROLS_STATE_AUX_0)) {
	
	// 获取mesh的当前世界变换矩阵
	Mat4 transform = mesh.getWorldTransform();

	// 获取mesh的方向向量
	Vec3 direction = transform.m00m10m20;

	// 计算移动的增量
	Vec3 delta_movement = direction * movement_speed * ifps;

	// 为mesh设置新位置
	mesh.setWorldTransform(translate(delta_movement) * transform);
}

或者,您也可更改世界变换矩阵的平移列(具体情况矩阵变换(Matrix Transformations)章节)来移动mesh:

源代码 (UnigineScript)
// 检查控制键是否被按下
if(engine.controls.getState(CONTROLS_STATE_AUX_0)) {
	
	// 获取mesh的当前世界变换矩阵
	Mat4 transform = mesh.getWorldTransform();

	// 获取mesh的方向向量
	Vec3 direction = transform.m00m10m20;

	// 计算移动的增量
	Vec3 delta_movement = direction * movement_speed * ifps;

	// 设置新位置
	// 此处您也可使用transform.m03m13m23 += delta_movement;
	transform.col3 += Vec4(delta_movement,1.0f);
	
	// 为mesh设置新的世界变换矩阵
	mesh.setWorldTransform(transform);
}

旋转

这部分包含了mesh旋转的实现。

您可以使用两种方式来旋转mesh,它们是setWorldTransform()函数或setWorldRotation()函数。 下面的例子使用的是setWorldRotation()函数:

源代码 (UnigineScript)
// 定义ObjectMeshStatic网格和移动速度
ObjectMeshStatic mesh;
float rotation_speed = 30.0f;

// 初始化自定义控制(controls)
void init_controls() {

	// 检测按键是否被按下以及更新指定control的状态
	// 您可以使用'o',也可以使用ASCII码(111)
	engine.controls.setStateKey(CONTROLS_STATE_AUX_1,'o');
}

// 将mesh作为节点添加给Editor
Node add_editor(Node node) {
	engine.editor.addNode(node);
	return node_remove(node);
}

/* world(世界)脚本的init()功能
 */
int init() {
	/* 创建一摄像机并将其添加给虚拟世界
	 */
	Player player = new PlayerSpectator();
	player.setDirection(Vec3(0.755f,-1.0f,0.25f));
	engine.game.setPlayer(player);
	
	// 将mesh添加给虚拟世界并设置材质
	mesh = add_editor(new ObjectMeshStatic("unigine_project/meshes/statue.mesh"));
	mesh.setMaterial("mesh_base", "*");

	// 调用init_controls()函数
	init_controls();

	return 1;
}

/* world(世界)脚本的update()功能
*/
int update() {

	// 获取帧时长
	float ifps = engine.game.getIFps();

	/* 这块代码用来旋转mesh
	*/
	// 检查控制键是否被按下
	if(engine.controls.getState(CONTROLS_STATE_AUX_1)) {
		// 设置沿Z轴的节点旋转
		mesh.setWorldRotation(mesh.getWorldRotation() * quat(rotateZ(rotation_speed * ifps)));
	}

	return 1;
}

在上面的例子中,通过按下键盘按键"o"就可以让节点向左旋转。

要想使用setWorldTransform()函数,须用下行代码替换setWorldRotation()函数:

源代码 (UnigineScript)
mesh.setWorldTransform(mesh.getWorldTransform() * rotateZ(rotation_speed * ifps));

组合运动

组合不同的运动控制不比只添加一种运动控制难多少。

下面的例子将一个mesh添加给了虚拟世界,并且您还能控制这个mesh。 您能通过键盘按键"o""["旋转它,能通过键盘按键"p"向前移动它。

源代码 (UnigineScript)
// 定义ObjectMeshStatic网格和移动速度
ObjectMeshStatic mesh;
float movement_speed = 5.0f;
float rotation_speed_left = 30.0f;
float rotation_speed_right = -30.0f;

// 初始化自定义控制(controls)
void init_controls() {
	// 检测按键是否被按下以及更新指定control的状态
	// 您可以使用'p',也可以使用ASCII码(112)
	engine.controls.setStateKey(CONTROLS_STATE_AUX_0,'p');
	engine.controls.setStateKey(CONTROLS_STATE_AUX_1,'o');
	engine.controls.setStateKey(CONTROLS_STATE_AUX_2,'[');
}
// 将mesh作为节点添加给Editor
Node add_editor(Node node) {
	engine.editor.addNode(node);
	return node_remove(node);
}

/* world(世界)脚本的init()功能
 */
int init() {
	/* 创建一摄像机并将其添加给虚拟世界
	 */
	Player player = new PlayerSpectator();
	player.setDirection(Vec3(0.755f,-1.0f,0.25f));
	engine.game.setPlayer(player);
	
	// 将mesh添加给虚拟世界并设置材质
	mesh = add_editor(new ObjectMeshStatic("unigine_project/meshes/statue.mesh"));
	mesh.setMaterial("mesh_base", "*");

	// 调用init_controls()函数
	init_controls();

	return 1;
}

/* world(世界)脚本的update()功能
*/
int update() {
	// 获取帧时长
	float ifps = engine.game.getIFps();

	// 检查用于向前移动的控制键是否被按下
	if(engine.controls.getState(CONTROLS_STATE_AUX_0)) {
	
		// 获取mesh的当前世界变换矩阵
		Mat4 transform = mesh.getWorldTransform();

		// 获取mesh的方向向量
		Vec3 direction = transform.m00m10m20;
		
		// 计算移动的增量
		Vec3 delta_movement = direction * movement_speed * ifps;

		// 为mesh设置新位置
		mesh.setWorldPosition(mesh.getWorldPosition() + delta_movement);
	}

	// 检查用于左旋转的控制键是否被按下
	if(engine.controls.getState(CONTROLS_STATE_AUX_1)) {
		// 设置节点的左旋转
		mesh.setWorldRotation(mesh.getWorldRotation() * quat(rotateZ(rotation_speed_left * ifps)));
	}

	// 检查用于右旋转的控制键是否被按下
	if(engine.controls.getState(CONTROLS_STATE_AUX_2)) {
		// 设置节点的右旋转
		mesh.setWorldRotation(mesh.getWorldRotation() * quat(rotateZ(rotation_speed_right * ifps)));
	}

	return 1;
}
最新更新: 2017-07-03