この文書では2次元物理シミュレーションPhysics2Dライブラリの基本的な使い方について説明します。
Contents
2次元物理シミュレーションPhysics2Dライブラリの基本的な使い方を学ぶためにサンプルシーンPrimitiveSceneを例に物理シーンの設定方法を見ていきます。
"sample/Physics2D/Physics2DSample/BasicScene/PrimitiveScene.cs"を参照してください。
物理シミュレーションのシーンを作る最小限の流れは以下の形になります。
実際にPrimitiveSceneを例としてシーン生成のコードの流れを見てみます。
using System;
using System.Text;
using Sce.PlayStation.Core;
using Sce.PlayStation.Core.Graphics;
using Sce.PlayStation.Core.Input;
using Sce.PlayStation.Core.Environment;
// Include 2D Physics Framework
using Sce.PlayStation.HighLevel.Physics2D;
public class PrimitiveScene : PhysicsScene
{
}
using System;
using System.Text;
using Sce.PlayStation.Core;
using Sce.PlayStation.Core.Graphics;
using Sce.PlayStation.Core.Input;
using Sce.PlayStation.Core.Environment;
// Include 2D Physics Framework
using Sce.PlayStation.HighLevel.Physics2D;
public class PrimitiveScene : PhysicsScene
{
public override void InitScene ()
{
// Create an empty simulation scene
base.InitScene();
}
}
using System;
using System.Text;
using Sce.PlayStation.Core;
using Sce.PlayStation.Core.Graphics;
using Sce.PlayStation.Core.Input;
using Sce.PlayStation.Core.Environment;
// Include 2D Physics Framework
using Sce.PlayStation.HighLevel.Physics2D;
public class PrimitiveScene : PhysicsScene
{
public PrimitiveScene()
{
InitScene();
}
public override void InitScene ()
{
// Create an empty simulation scene
base.InitScene();
}
}
public override void InitScene ()
{
// Create an empty simulation scene
base.InitScene();
...
...
...
// Box Shape Setting PhysicsShape( "width", "height" )
Vector2 wall_width = new Vector2(50, 8);
sceneShapes[0] = new PhysicsShape(wall_width);
Vector2 wall_height = new Vector2(8, 30);
sceneShapes[1] = new PhysicsShape(wall_height);
Vector2 box_width = new Vector2(2.0f, 2.0f);
sceneShapes[2] = new PhysicsShape(box_width);
// Sphere Shape Setting PhysicsShape( "radius" )
float sphere_width = 2.0f;
sceneShapes[3] = new PhysicsShape(sphere_width);
Vector2[] test_point = new Vector2[10];
for (int i = 0; i < 10; i++)
{
test_point[i] = new Vector2(rand_gen.Next(-1000, 1000), rand_gen.Next(-1000, 1000)) * 2.0f / 1000.0f;
}
// Convex Shape Setting (by using random points)
sceneShapes[4] = PhysicsShape.CreateConvexHull(test_point, 10);
numShape = 5;
...
...
...
}
ボックスの縦横半分の長さをPhysicsShapeコンストラクタの引数に与えます。
Vector2 wall_width = new Vector2(50, 8);
sceneShapes[0] = new PhysicsShape(wall_width);
球の半径を設定したfloat値をPhysicsShapeコンストラクタの引数に与えます。
float sphere_width = 2.0f;
sceneShapes[3] = new PhysicsShape(sphere_width);
ランダムな頂点を10個作り、ランダムな10個の頂点をもとに凸包を作って凸多角形を生成しています。
Vector2[] test_point = new Vector2[10];
for (int i = 0; i < 10; i++)
{
test_point[i] = new Vector2(rand_gen.Next(-1000, 1000), rand_gen.Next(-1000, 1000)) * 2.0f / 1000.0f;
}
sceneShapes[4] = PhysicsShape.CreateConvexHull(test_point, 10);
ここでCreateConvexHullは任意の頂点列を与えて、凸包を生成するAPIです。
1つずつ衝突形状を登録するたびにnumShapeをインクリメントしてもいいですが、PrimitiveSceneでは衝突形状を登録した後でnumShapeを設定しています。
numShape = 5;
まず、剛体にはいくつかのタイプがあります。
public override void InitScene()
{
...
...
...
// Create static walls to limit the range of action of active rigid sceneBodies
{
// new PhysicsBody( "shape of the body", "mass of the body(kg)" )
sceneBodies[numBody] = new PhysicsBody(sceneShapes[0], PhysicsUtility.FltMax);
// Set the position & the rotation
sceneBodies[numBody].position = new Vector2(0, -wall_height.Y);
sceneBodies[numBody].rotation = 0;
// Make shapeIndex consistent with what we set as convex shape
sceneBodies[numBody].shapeIndex = 0;
numBody++;
sceneBodies[numBody] = new PhysicsBody(sceneShapes[1], PhysicsUtility.FltMax);
sceneBodies[numBody].position = new Vector2(wall_width.X, 0);
sceneBodies[numBody].rotation = 0;
sceneBodies[numBody].shapeIndex = 1;
numBody++;
sceneBodies[numBody] = new PhysicsBody(sceneShapes[1], PhysicsUtility.FltMax);
sceneBodies[numBody].position = new Vector2(-wall_width.X, 0);
sceneBodies[numBody].rotation = 0;
sceneBodies[numBody].shapeIndex = 1;
numBody++;
sceneBodies[numBody] = new PhysicsBody(sceneShapes[0], PhysicsUtility.FltMax);
sceneBodies[numBody].position = new Vector2(0, wall_height.Y);
sceneBodies[numBody].rotation = 0;
sceneBodies[numBody].shapeIndex = 0;
numBody++;
}
...
...
...
}
sceneBodies[numBody] = new PhysicsBody(sceneShapes[0], PhysicsUtility.FltMax);
sceneBodies[numBody].position = new Vector2(0, -wall_height.Y);
sceneBodies[numBody].rotation = 0;
sceneBodies[numBody].shapeIndex = 0;
numBody++;
// Create dynamic rigid sceneBodies
{
// Create a box-shaped dynamic rigid body
{
sceneBodies[numBody] = new PhysicsBody(sceneShapes[2], 1.0f);
sceneBodies[numBody].position = new Vector2(-10.0f, -5.0f);
sceneBodies[numBody].rotation = PhysicsUtility.GetRadian(30.0f);
sceneBodies[numBody].shapeIndex = 2;
numBody++;
}
// Create a sphere-shaped dynamic rigid body
{
sceneBodies[numBody] = new PhysicsBody(sceneShapes[3], 1.0f);
sceneBodies[numBody].position = new Vector2(0.0f, -5.0f);
sceneBodies[numBody].rotation = 0;
sceneBodies[numBody].shapeIndex = 3;
sceneBodies[numBody].colFriction = 0.01f;
numBody++;
}
// Create a convex-shaped dynamic rigid body
{
sceneBodies[numBody] = new PhysicsBody(sceneShapes[4], 1.0f);
sceneBodies[numBody].position = new Vector2(10.0f, -5.0f);
sceneBodies[numBody].rotation = 0;
sceneBodies[numBody].shapeIndex = 4;
numBody++;
}
}
ここではボックスとなるDynamic剛体の設定を行っています。
sceneBodies[numBody] = new PhysicsBody(sceneShapes[2], 1.0f);
sceneBodies[numBody].position = new Vector2(-10.0f, -5.0f);
sceneBodies[numBody].rotation = PhysicsUtility.GetRadian(30.0f);
sceneBodies[numBody].shapeIndex = 2;
numBody++;
sceneBodies[numBody] = new PhysicsBody(sceneShapes[3], 1.0f);
sceneBodies[numBody].position = new Vector2(0.0f, -5.0f);
sceneBodies[numBody].rotation = 0;
sceneBodies[numBody].shapeIndex = 3;
sceneBodies[numBody].colFriction = 0.01f;
numBody++;
sceneBodies[numBody] = new PhysicsBody(sceneShapes[4], 1.0f);
sceneBodies[numBody].position = new Vector2(10.0f, -5.0f);
sceneBodies[numBody].rotation = 0;
sceneBodies[numBody].shapeIndex = 4;
numBody++;
// Create a kinematic rigid body whose shape is box
{
sceneBodies[numBody] = new PhysicsBody(sceneShapes[2], 1.0f);
sceneBodies[numBody].position = new Vector2(-10.0f, 15.0f);
sceneBodies[numBody].rotation = PhysicsUtility.GetRadian(30.0f);
sceneBodies[numBody].shapeIndex = 2;
sceneBodies[numBody].SetBodyKinematic();
index0 = numBody++;
}
// Create a sphere-shaped kinematic rigid body
{
sceneBodies[numBody] = new PhysicsBody(sceneShapes[3], 1.0f);
sceneBodies[numBody].position = new Vector2(0.0f, 15.0f);
sceneBodies[numBody].rotation = 0;
sceneBodies[numBody].shapeIndex = 3;
sceneBodies[numBody].colFriction = 0.01f;
sceneBodies[numBody].SetBodyKinematic();
index1 = numBody++;
}
// Create a convex-shaped kinematic rigid body
{
sceneBodies[numBody] = new PhysicsBody(sceneShapes[4], 1.0f);
sceneBodies[numBody].position = new Vector2(10.0f, 15.0f);
sceneBodies[numBody].rotation = 0;
sceneBodies[numBody].shapeIndex = 4;
sceneBodies[numBody].SetBodyKinematic();
index2 = numBody++;
}
sceneBodies[numBody] = new PhysicsBody(sceneShapes[2], 1.0f);
sceneBodies[numBody].position = new Vector2(-10.0f, 15.0f);
sceneBodies[numBody].rotation = PhysicsUtility.GetRadian(30.0f);
sceneBodies[numBody].shapeIndex = 2;
sceneBodies[numBody].SetBodyKinematic();
index0 = numBody++;
// Game controller handling
public override void KeyboradFunc(GamePadButtons button)
{
switch (button)
{
case GamePadButtons.Square:
//
// isKinematicOrStatic() checks the mass of the rigid body and determines whether a body is kinematic or static
// backToDynamic() cannot be called for rigid sceneBodies not set up with setKinematic()
//
if (sceneBodies[index0].IsKinematic())
sceneBodies[index0].BackToDynamic();
else
sceneBodies[index0].SetBodyKinematic();
if (sceneBodies[index1].IsKinematic())
sceneBodies[index1].BackToDynamic();
else
sceneBodies[index1].SetBodyKinematic();
if (sceneBodies[index2].IsKinematic())
sceneBodies[index2].BackToDynamic();
else
sceneBodies[index2].SetBodyKinematic();
break;
default:
break;
}
}
さて、InitScene()の中で剛体の初期配置について見てきましたが、InitScene()で使われているシーンの特性の設定について説明します。
public override void InitScene ()
{
// Create an empty simulation scene
base.InitScene();
sceneName = "PrimitiveScene";
// Set the restitution coefficient a bit stronger
this.restitutionCoeff = 0.8f;
sceneNameはシーン名を保持する文字列の変数で"PrimitiveScene"をセットしています。
this.restitutionCoeff = 0.8f;
シーンの特性である反発に対する反発係数の設定をしていて、反発をきちんと生じるシーンに設定しています。
シーン内での衝突の特性を決めるパラメータとしては以下の値が設定可能です。
まずはシェーダープログラムに与える頂点バッファが必要になります。
public class PrimitiveScene : PhysicsScene
{
// Vertex Buffer for Body Rendering
private VertexBuffer[] vertices = new VertexBuffer[100];
public PrimitiveScene()
{
// Simulation Scene Set Up
InitScene();
// Setup for Rendering Object
for (int i = 0; i < numShape; i++)
{
if (sceneShapes[i].numVert == 0)
{
vertices[i] = new VertexBuffer(37, VertexFormat.Float3);
}
else
{
vertices[i] = new VertexBuffer(sceneShapes[i].numVert + 1, VertexFormat.Float3);
}
ここでPhysicsShapeの構造を確認しておきます。
public partial class PhysicsShape
{
public int numVert;
public Vector2[] vertList = new Vector2[30];
...
...
...
}
PhysicsShapeの構造にもとづき、頂点バッファに頂点をセットしている部分は以下です。
// Line Rendering for Object
private void MakeLineListConvex(PhysicsShape con, VertexBuffer vertices)
{
if (con.numVert == 0)
{
float[] vertex = new float[3 * 37];
int i = 0;
float rad = con.vertList[0].X;
for (float th1 = 0.0f; th1 < 360.0f; th1 = th1 + 10.0f)
{
float th1_rad = th1 / 180.0f * PhysicsUtility.Pi;
float x1 = rad * (float)Math.Cos(th1_rad);
float y1 = rad * (float)Math.Sin(th1_rad);
vertex[3 * i + 0] = x1;
vertex[3 * i + 1] = y1;
vertex[3 * i + 2] = 0.0f;
i++;
}
vertex[3 * i + 0] = vertex[3 * 0 + 0];
vertex[3 * i + 1] = vertex[3 * 0 + 1];
vertex[3 * i + 2] = vertex[3 * 0 + 2];
vertices.SetVertices(0, vertex);
}
else
{
float[] vertex = new float[3 * (con.numVert + 1)];
int i;
for (i = 0; i < con.numVert; i++)
{
Vector2 v1;
v1 = con.vertList[i];
vertex[3 * i + 0] = v1.X;
vertex[3 * i + 1] = v1.Y;
vertex[3 * i + 2] = 0.0f;
}
vertex[3 * i + 0] = vertex[3 * 0 + 0];
vertex[3 * i + 1] = vertex[3 * 0 + 1];
vertex[3 * i + 2] = vertex[3 * 0 + 2];
vertices.SetVertices(0, vertex);
}
}
if (con.numVert == 0)
{
float[] vertex = new float[3 * 37];
int i = 0;
float rad = con.vertList[0].X;
for (float th1 = 0.0f; th1 < 360.0f; th1 = th1 + 10.0f)
{
float th1_rad = th1 / 180.0f * PhysicsUtility.Pi;
float x1 = rad * (float)Math.Cos(th1_rad);
float y1 = rad * (float)Math.Sin(th1_rad);
vertex[3 * i + 0] = x1;
vertex[3 * i + 1] = y1;
vertex[3 * i + 2] = 0.0f;
i++;
}
vertex[3 * i + 0] = vertex[3 * 0 + 0];
vertex[3 * i + 1] = vertex[3 * 0 + 1];
vertex[3 * i + 2] = vertex[3 * 0 + 2];
vertices.SetVertices(0, vertex);
}
else
{
float[] vertex = new float[3 * (con.numVert + 1)];
int i;
for (i = 0; i < con.numVert; i++)
{
Vector2 v1;
v1 = con.vertList[i];
vertex[3 * i + 0] = v1.X;
vertex[3 * i + 1] = v1.Y;
vertex[3 * i + 2] = 0.0f;
}
vertex[3 * i + 0] = vertex[3 * 0 + 0];
vertex[3 * i + 1] = vertex[3 * 0 + 1];
vertex[3 * i + 2] = vertex[3 * 0 + 2];
vertices.SetVertices(0, vertex);
}
形状をライン描画するために最後の頂点として最初の頂点と同じ座標を与えています。
// Draw objects
public override void DrawAllBody(ref GraphicsContext graphics, ref ShaderProgram program, Matrix4 renderMatrix, int click_index)
{
for (int j = 0; j < numShape; j++)
{
graphics.SetVertexBuffer(0, vertices[j]);
for (int i = 0; i < numBody; i++)
{
uint index = sceneBodies[i].shapeIndex;
if (j != index) continue;
Matrix4 rotationMatrix = Matrix4.RotationZ(sceneBodies[i].rotation);
Matrix4 transMatrix = Matrix4.Translation(
new Vector3(sceneBodies[i].position.X, sceneBodies[i].position.Y, 0.0f));
Matrix4 local_rotationMatrix = Matrix4.RotationZ(sceneBodies[i].localRotation);
Matrix4 local_transMatrix = Matrix4.Translation(
new Vector3(sceneBodies[i].localPosition.X, sceneBodies[i].localPosition.Y, 0.0f));
Matrix4 WorldMatrix = renderMatrix * transMatrix * rotationMatrix * local_transMatrix * local_rotationMatrix;
program.SetUniformValue(0, ref WorldMatrix);
if (i == click_index)
{
Vector3 color = new Vector3(1.0f, 0.0f, 0.0f);
program.SetUniformValue(1, ref color);
}
else
{
Vector3 color = new Vector3(0.0f, 1.0f, 1.0f);
program.SetUniformValue(1, ref color);
}
if (sceneShapes[index].numVert == 0)
graphics.DrawArrays(DrawMode.LineStrip, 0, 37);
else
graphics.DrawArrays(DrawMode.LineStrip, 0, sceneShapes[index].numVert + 1);
}
}
}
Matrix4 rotationMatrix = Matrix4.RotationZ(sceneBodies[i].rotation);
Matrix4 transMatrix = Matrix4.Translation(
new Vector3(sceneBodies[i].position.X, sceneBodies[i].position.Y, 0.0f));
Matrix4 local_rotationMatrix = Matrix4.RotationZ(sceneBodies[i].localRotation);
Matrix4 local_transMatrix = Matrix4.Translation(
new Vector3(sceneBodies[i].localPosition.X, sceneBodies[i].localPosition.Y, 0.0f));
Matrix4 WorldMatrix = renderMatrix * transMatrix * rotationMatrix * local_transMatrix * local_rotationMatrix;
program.SetUniformValue(0, ref WorldMatrix);
変換の行列を設定したら、後は元の衝突形状の頂点をシェーダーに与えて描画を行うだけで良いのです。
if (sceneShapes[index].numVert == 0)
graphics.DrawArrays(DrawMode.LineStrip, 0, 37);
else
graphics.DrawArrays(DrawMode.LineStrip, 0, sceneShapes[index].numVert + 1);
public class PrimitiveScene : PhysicsScene
{
...
...
...
private VertexBuffer colVert = null;
...
...
...
public PrimitiveScene()
{
...
...
...
// VertexBuffer for contact points debug rendering
{
colVert = new VertexBuffer(4, VertexFormat.Float3);
const float scale = 0.2f;
float[] vertex = new float[]
{
-1.0f, -1.0f, 0.0f,
1.0f, -1.0f, 0.0f,
1.0f, 1.0f, 0.0f,
-1.0f, 1.0f, 0.0f
};
for (int i = 0; i < 12; i++)
vertex[i] = vertex[i] * scale;
colVert.SetVertices(0, vertex);
}
// Debug rendering for contact points(RigidBody A <=> RigidBody B) and AABB(Axis Aligned Bounding Box)
public override void DrawAdditionalInfo(ref GraphicsContext graphics, ref ShaderProgram program, Matrix4 renderMatrix)
{
// Draw contact points
graphics.SetVertexBuffer(0, colVert);
for (uint i = 0; i < numPhysicsSolverPair; i++)
{
// Collision point for RigidBody A
{
Matrix4 transMatrix = Matrix4.Translation(
new Vector3(solverPair[i].resA.X, solverPair[i].resA.Y, 0.0f));
Matrix4 WorldMatrix = renderMatrix * transMatrix;
program.SetUniformValue(0, ref WorldMatrix);
Vector3 color = new Vector3(1.0f, 0.0f, 0.0f);
program.SetUniformValue(1, ref color);
graphics.DrawArrays(DrawMode.TriangleFan, 0, 4);
}
// Collision point for RigidBody B
{
Matrix4 transMatrix = Matrix4.Translation(
new Vector3(solverPair[i].resB.X, solverPair[i].resB.Y, 0.0f));
Matrix4 WorldMatrix = renderMatrix * transMatrix;
program.SetUniformValue(0, ref WorldMatrix);
Vector3 color = new Vector3(1.0f, 0.0f, 0.0f);
program.SetUniformValue(1, ref color);
graphics.DrawArrays(DrawMode.TriangleFan, 0, 4);
}
}
Matrix4 transMatrix = Matrix4.Translation(
new Vector3(solverPair[i].resA.X, solverPair[i].resA.Y, 0.0f));
Matrix4 transMatrix = Matrix4.Translation(
new Vector3(solverPair[i].resB.X, solverPair[i].resB.Y, 0.0f));
public class PrimitiveScene : PhysicsScene
{
...
...
...
private VertexBuffer aabbVert = null;
...
...
...
public PrimitiveScene()
{
...
...
...
// VertexBuffer for AABB debug rendering
{
aabbVert = new VertexBuffer(5, VertexFormat.Float3);
float[] vertex = new float[]
{
0.0f, 0.0f, 0.0f,
1.0f, 0.0f, 0.0f,
1.0f, 1.0f, 0.0f,
0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f,
};
aabbVert.SetVertices(0, vertex);
}
// Debug rendering for contact points(RigidBody A <=> RigidBody B) and AABB(Axis Aligned Bounding Box)
public override void DrawAdditionalInfo(ref GraphicsContext graphics, ref ShaderProgram program, Matrix4 renderMatrix)
{
...
...
...
// Draw AABB Bounding Box
graphics.SetVertexBuffer(0, aabbVert);
for (uint i = 0; i < numBody; i++)
{
Matrix4 scaleMatrix = new Matrix4(
sceneBodies[i].aabbMax.X - sceneBodies[i].aabbMin.X, 0.0f, 0.0f, 0.0f,
0.0f, sceneBodies[i].aabbMax.Y - sceneBodies[i].aabbMin.Y, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
);
Matrix4 transMatrix = Matrix4.Translation(
new Vector3(sceneBodies[i].aabbMin.X, sceneBodies[i].aabbMin.Y, 0.0f));
Matrix4 WorldMatrix = renderMatrix * transMatrix * scaleMatrix;
program.SetUniformValue(0, ref WorldMatrix);
Vector3 color = new Vector3(1.0f, 1.0f, 0.0f);
program.SetUniformValue(1, ref color);
graphics.DrawArrays(DrawMode.LineStrip, 0, 5);
}
バウンディングボックスの大きさの取得
Matrix4 scaleMatrix = new Matrix4(
sceneBodies[i].aabbMax.X - sceneBodies[i].aabbMin.X, 0.0f, 0.0f, 0.0f,
0.0f, sceneBodies[i].aabbMax.Y - sceneBodies[i].aabbMin.Y, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f
);
バウンディングボックスの位置の取得
Matrix4 transMatrix = Matrix4.Translation(
new Vector3(sceneBodies[i].aabbMin.X, sceneBodies[i].aabbMin.Y, 0.0f));
バウンディングボックスの大きさを調整した後に、正しい位置に描画するため、以下の順番で描画のための行列の設定を行います。
Matrix4 WorldMatrix = renderMatrix * transMatrix * scaleMatrix;
public override void ReleaseScene()
{
for (int i = 0; i < numShape; i++)
if(vertices[i] != null)
vertices[i].Dispose();
if(aabbVert != null) aabbVert.Dispose();
if(colVert != null) colVert.Dispose();
}
以上でPrimitiveSceneの概要を見てきましたが、実際にいろいろな値を変えたりすることで、 結果がどのように変わるのかを試してみることをお勧めします。
回転方向の拘束とは、ジョイントで結合された剛体Aと剛体Bがアンカーポイントを中心として、
を設定します。
並進方向の拘束とは、ジョイントで結合された剛体Aと剛体Bがアンカーポイントを中心として、
を設定します。
public override void InitScene ()
{
...
...
...
// Link a box rigid body to the scene with a fixed joint.
// If you just want to fix a rigid body to the scene perfectly, it is best simply making a static rigidbody.
{
sceneBodies[numBody] = new PhysicsBody(sceneShapes[2], 10.0f);
sceneBodies[numBody].position = new Vector2(-30.0f, 0.0f);
sceneBodies[numBody].shapeIndex = 2;
numBody++;
PhysicsBody b1 = sceneBodies[0];
PhysicsBody b2 = sceneBodies[numBody-1];
sceneJoints[numJoint] = new PhysicsJoint(b1, b2, (b2.position), 0, (uint)numBody-1);
sceneJoints[numJoint].axis1Lim = new Vector2(1, 0);
sceneJoints[numJoint].axis2Lim = new Vector2(0, 1);
sceneJoints[numJoint].angleLim = 1;
numJoint++;
}
PhysicsBody b1 = sceneBodies[0];
PhysicsBody b2 = sceneBodies[numBody-1];
sceneJoints[numJoint] = new PhysicsJoint(b1, b2, (b2.position), 0, (uint)numBody-1);
sceneJoints[numJoint].axis1Lim = new Vector2(1, 0);
sceneJoints[numJoint].axis2Lim = new Vector2(0, 1);
sceneJoints[numJoint].angleLim = 1;
の順で指定が行われています。
ここで仮に
sceneJoints[numJoint].angleLim = 0;
と指定していたなら、回転方向は自由になります。
同様に仮に
sceneJoints[numJoint].axis1Lim = new Vector2(0, 0);
と指定していたなら、X軸方向の拘束がなくなり自由移動になります。
同様に仮に
sceneJoints[numJoint].axis2Lim = new Vector2(0, 0);
と指定していたなら、Y軸方向の拘束がなくなり自由移動になります。
もしも仮に
sceneJoints[numJoint].axis1Lim = new Vector2(0, 0);
sceneJoints[numJoint].axis2Lim = new Vector2(0, 0);
sceneJoints[numJoint].angleLim = 0;
とするならば、ジョイントの拘束条件を何も指定していないことになるので、ジョイントを設定していないのと同じになります。
public override void InitScene ()
{
...
...
...
// Link a box rigid body to the scene with a rotation joint(with angle constraints)
{
sceneBodies[numBody] = new PhysicsBody(sceneShapes[2], 10.0f);
sceneBodies[numBody].position = new Vector2(-20.0f, 0.0f);
sceneBodies[numBody].shapeIndex = 2;
numBody++;
PhysicsBody b1 = sceneBodies[0];
PhysicsBody b2 = sceneBodies[numBody-1];
sceneJoints[numJoint] = new PhysicsJoint(b1, b2, (b2.position), 0, (uint)numBody-1);
sceneJoints[numJoint].axis1Lim = new Vector2(1, 0);
sceneJoints[numJoint].axis2Lim = new Vector2(0, 1);
sceneJoints[numJoint].angleLim = 1;
sceneJoints[numJoint].angleLower = PhysicsUtility.GetRadian(-45.0f);
sceneJoints[numJoint].angleUpper = PhysicsUtility.GetRadian(45.0f);
numJoint++;
}
-45度から45度の制約付き角度制限を行っているのは以下の部分です。
sceneJoints[numJoint].angleLim = 1;
sceneJoints[numJoint].angleLower = PhysicsUtility.GetRadian(-45.0f);
sceneJoints[numJoint].angleUpper = PhysicsUtility.GetRadian(45.0f);
public override void InitScene ()
{
...
...
...
// Link a box rigid body to the scene with a horizontal slider joint (with movement constraints)
{
sceneBodies[numBody] = new PhysicsBody(sceneShapes[2], 10.0f);
sceneBodies[numBody].position = new Vector2(0.0f, 0.0f);
sceneBodies[numBody].shapeIndex = 2;
numBody++;
PhysicsBody b1 = sceneBodies[0];
PhysicsBody b2 = sceneBodies[numBody-1];
sceneJoints[numJoint] = new PhysicsJoint(b1, b2, (b2.position), 0, (uint)numBody-1);
sceneJoints[numJoint].axis1Lim = new Vector2(1, 0);
sceneJoints[numJoint].axis2Lim = new Vector2(0, 1);
sceneJoints[numJoint].axis2Lower = -10.0f;
sceneJoints[numJoint].axis2Upper = 10.0f;
sceneJoints[numJoint].angleLim = 1;
numJoint++;
}
-10mから+10mまでのY軸方向の制約付き拘束を行っているのは以下の部分です。
sceneJoints[numJoint].axis2Lim = new Vector2(0, 1);
sceneJoints[numJoint].axis2Lower = -10.0f;
sceneJoints[numJoint].axis2Upper = 10.0f;
public override void InitScene ()
{
...
...
...
// Link a box rigid body to the scene with a horizontal slider joint (with movement constraints)
{
sceneBodies[numBody] = new PhysicsBody(sceneShapes[2], 10.0f);
sceneBodies[numBody].position = new Vector2(0.0f, 0.0f);
sceneBodies[numBody].shapeIndex = 2;
numBody++;
PhysicsBody b1 = sceneBodies[0];
PhysicsBody b2 = sceneBodies[numBody-1];
sceneJoints[numJoint] = new PhysicsJoint(b1, b2, (b2.position), 0, (uint)numBody-1);
sceneJoints[numJoint].axis1Lim = new Vector2(1, 0);
sceneJoints[numJoint].axis1Lower = -10.0f;
sceneJoints[numJoint].axis1Upper = 10.0f;
sceneJoints[numJoint].axis2Lim = new Vector2(0, 1);
sceneJoints[numJoint].angleLim = 1;
numJoint++;
// The horizontal slider joint is quite slippy,
// so to make the rigid body stop we add some air friction
b2.airFriction = 0.01f;
}
垂直方向における移動制約の例と同様に水平方向の移動制約の設定を行っています。
sceneJoints[numJoint].axis1Lim = new Vector2(1, 0);
sceneJoints[numJoint].axis1Lower = -10.0f;
sceneJoints[numJoint].axis1Upper = 10.0f;
// The horizontal slider joint is quite slippy,
// so to make the rigid body stop we add some air friction
b2.airFriction = 0.01f;