I need help with ZGEBullet zbtCreateHeightfieldTerrainShape

All topics about ZGameEditor goes here.

Moderator: Moderators

Post Reply
User avatar
Ats
Posts: 927
Joined: Fri Sep 28, 2012 10:05 am
Contact:

I need help with ZGEBullet zbtCreateHeightfieldTerrainShape

Post by Ats »

Hello.

I’m trying to make sense of Rado1’s ZGEBullet examples. In his Demos 2 and 3, he uses a randomly generated terrain with physics, which would be quite convenient for what I’m doing. However, I’m struggling with some small details that make it difficult to modify the size and number of vertices for my own purpose, especially since the collision terrain is invisible.

Let’s take a look at Demo 2:
https://github.com/Rado-1/ZgeBullet/blo ... o2.zgeproj

First, we have a 10×10 array that will hold the coordinates of the vertices of the physical terrain:

Code: Select all

float[10,10] Terrain;
Then, a ZExpression is used to generate a random TerrainMesh, starting from a 2D MeshBox with an 8×8 XYCount:

Code: Select all

float h = noise3(v.X*2, v.Y*2, App.Time)*1.5;
v.Z = h;
Terrain[floor((v.X+1)*4.9), floor((v.Y+1)*4.9)] = h;
Right from the start, why is the MeshBox 8×8 while the array is 10×10? This makes filling the array a bit awkward: Terrain[floor((v.X+1)*4.9), floor((v.Y+1)*4.9)]
Why not start with a one-to-one correspondence?

Then the terrain physics are created:

Code: Select all

xptr sh = zbtCreateHeightfieldTerrainShape(Terrain, 10, 10, -2, 2, ZBT_AXIS_Y_LINEAR, FALSE, FALSE);
zbtSetShapeLocalScaling(sh, 9, 10, 9);
xptr rb = zbtCreateRigidBodyXYZ(0, sh, 0, 0, 0, 0, 0, 0);
The physical terrain is 10×10, with a height varying from -2 to 2.
We specify that the up axis is ZBT_AXIS_Y_LINEAR.
On top of that, a scale is applied to the terrain physics:
  • x9 on the X axis
  • x10 on the Y axis (in the terrain physics, Y represent the vertical axis)
  • x9 on the Z axis
Why those numbers? How do they correspond to what follows with the mesh scale?

Finally, the terrain mesh is displayed using a RenderTransformGroup with the following settings:
  • Scale.X = 40
  • Scale.Y = 40
  • Scale.Z = 10 (in the terrain mesh, Z represent the vertical axis)
  • Rotate.X = -0.25 (rotate 90° so the Z axis is facing up)
  • Rotate.Y = -0.25 (WHY is it rotated on that axis!?)

I’m trying to make it as simple as possible to reuse, because once I adapt it to my game, there’s no way to tell whether the terrain physics actually match the terrain mesh.

Thanks
User avatar
Kjell
Posts: 1980
Joined: Sat Feb 23, 2008 11:15 pm

Re: I need help with ZGEBullet zbtCreateHeightfieldTerrainShape

Post by Kjell »

Hi Ats,
Ats wrote: Sat Dec 06, 2025 4:01 pmwhy is the MeshBox 8×8 while the array is 10×10?
This is due to ZGE's non-standard subdivision values. If i recall correctly, this "issue" did get raised a long long time ago, but Ville didn't want to change the values because it would break backwards compatibility.

Anyway, in ZGE a Grid2DOnly MeshBox with a XCount and YCount of 8 gives you the following mesh:

Image

So, over each axis you end up with 10 vertices ( hence the 10x10 array size ) and 9 faces ( hence the local scale of 9 for both X and Z axes ).

K
User avatar
Ats
Posts: 927
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: I need help with ZGEBullet zbtCreateHeightfieldTerrainShape

Post by Ats »

All right. Thanks for the clarification. So :

Code: Select all

facesX = XCount + 1
facesY = YCount + 1
faces = (XCount + 1) × (YCount + 1)
vertsX = Terrain.SizeDim1 = XCount + 2
vertsY = Terrain.SizeDim2 = YCount + 2
But yeah, that makes the next line complicated: Terrain[floor((v.X+1)*4.9), floor((v.Y+1)*4.9)] = h;

Code: Select all

byte gridSizeX = Terrain.SizeDim1;
byte gridSizeY = Terrain.SizeDim2;
float ix = clamp( floor(((v.X + 1) * 0.5 * (gridSizeX - 1)) + 0.5), 0, gridSizeX - 1 );
float iy = clamp( floor(((v.Y + 1) * 0.5 * (gridSizeY - 1)) + 0.5), 0, gridSizeY - 1 );
Terrain[ix, iy] = h;
What about the visual rotation of the ground on the Y axis (Rotate.Y = -0.25)?
Is that because the vertices of the mesh aren’t stored (or read) in the same order as the Terrain array?
If so, wouldn’t it be better to bake the rotations directly into the vertex generation so that the visual mesh, the physics terrain, and the logic are all properly aligned?

I would like to be sure that what I see is what I get, because of the invisible physics :lol:
User avatar
Kjell
Posts: 1980
Joined: Sat Feb 23, 2008 11:15 pm

Re: I need help with ZGEBullet zbtCreateHeightfieldTerrainShape

Post by Kjell »

Hi Ats,
Ats wrote: Sun Dec 07, 2025 1:01 pmBut yeah, that makes the next line complicated: Terrain[floor((v.X+1)*4.9), floor((v.Y+1)*4.9)] = h;
You could change the MeshBox scale to 0.5 ( and i'd recommend round instead of floor ) so you can use:

Code: Select all

Terrain[round((V.X+0.5)*9), round((V.Y+0.5)*9)] = V.Z;
Or you could set the scale to the desired final size, whatever you find most intuitive.
Ats wrote: Sun Dec 07, 2025 1:01 pmWhat about the visual rotation of the ground on the Y axis (Rotate.Y = -0.25)?
Is that because the vertices of the mesh aren’t stored (or read) in the same order as the Terrain array?
I don't know what the expected vertex order is for HeightfieldTerrainShape in Bullet, but this is something you need to be aware of in ZGE as well. If you for example rotate your Grid2DOnly mesh over the x-axis, this basically flips the y coordinate of your array since OpenGL uses a right-handed coordinate system. Here's an example illustrating this ( check the ZExpression in App.OnRender ):

Code: Select all

<?xml version="1.0" encoding="iso-8859-1" ?>
<ZApplication Name="App" Caption="ZGameEditor application" CameraPosition="4.5 9 14.5" CameraRotation="0.125 0 0" FileVersion="2">
  <OnLoaded>
    <ZExternalLibrary ModuleName="OpenGL32">
      <Source>
<![CDATA[//

void glBegin(int mode){}
void glEnd(){}
void glVertex3f(float x, float y, float z){}]]>
      </Source>
    </ZExternalLibrary>
  </OnLoaded>
  <OnRender>
    <UseMaterial Material="TerrainMaterial"/>
    <RenderMesh Mesh="TerrainMesh"/>
    <RenderSetColor Color="1 0 0 1"/>
    <ZExpression>
      <Expression>
<![CDATA[//

glBegin(1);

for(int x=0; x<10; x++)
{
  for(int y=0; y<10; y++)
  {
    glVertex3f(x, 0, y);
    glVertex3f(x, Terrain[x,9-y], y); // 9-y due to z-axis being inverted in OpenGL
  }
}

glEnd();]]>
      </Expression>
    </ZExpression>
  </OnRender>
  <Content>
    <Array Name="Terrain" Dimensions="1" SizeDim1="10" SizeDim2="10"/>
    <Mesh Name="TerrainMesh">
      <Producers>
        <MeshBox Scale="0.5 0.5 1" XCount="8" YCount="8" Grid2DOnly="255"/>
        <MeshExpression>
          <Expression>
<![CDATA[//

V.Z = rnd();

//

Terrain[round((V.X+0.5)*9), round((V.Y+0.5)*9)] = V.Z;]]>
          </Expression>
        </MeshExpression>
        <MeshTransform Scale="9 9 1" Position="4.5 0 4.5" Rotation="-0.25 0 0"/>
      </Producers>
    </Mesh>
    <Material Name="TerrainMaterial" Shading="2" Light="0"/>
  </Content>
</ZApplication>
Ats wrote: Sun Dec 07, 2025 1:01 pmIf so, wouldn’t it be better to bake the rotations directly into the vertex generation so that the visual mesh, the physics terrain, and the logic are all properly aligned?
Baking in the transformation in your mesh ( using MeshTransform ) is usually the better option because then it only has to be done once instead of every frame. In fact, i'd just do this ..

Code: Select all

<?xml version="1.0" encoding="iso-8859-1" ?>
<ZApplication Name="App" Caption="ZGameEditor application" CameraPosition="4.5 9 14.5" CameraRotation="0.125 0 0" FileVersion="2">
  <OnLoaded>
    <ZExternalLibrary ModuleName="OpenGL32">
      <Source>
<![CDATA[//

void glBegin(int mode){}
void glEnd(){}
void glVertex3f(float x, float y, float z){}]]>
      </Source>
    </ZExternalLibrary>
  </OnLoaded>
  <OnRender>
    <UseMaterial Material="TerrainMaterial"/>
    <RenderMesh Mesh="TerrainMesh"/>
    <RenderSetColor Color="1 0 0 1"/>
    <ZExpression>
      <Expression>
<![CDATA[//

glBegin(1);

for(int x=0; x<10; x++)
{
  for(int y=0; y<10; y++)
  {
    glVertex3f(x, 0, y);
    glVertex3f(x, Terrain[x,y], y);
  }
}

glEnd();]]>
      </Expression>
    </ZExpression>
  </OnRender>
  <Content>
    <Array Name="Terrain" Dimensions="1" SizeDim1="10" SizeDim2="10"/>
    <Mesh Name="TerrainMesh">
      <Producers>
        <MeshBox Scale="0.5 0.5 1" XCount="8" YCount="8" Grid2DOnly="255"/>
        <MeshExpression>
          <Expression>
<![CDATA[//

float x = round((V.X+0.5)*9);
float y = round((0.5-V.Y)*9);

//

V.X = x;
V.Y = rnd();
V.Z = y;

//

Terrain[x, y] = V.Y;]]>
          </Expression>
        </MeshExpression>
      </Producers>
    </Mesh>
    <Material Name="TerrainMaterial" Shading="2" Light="0"/>
  </Content>
</ZApplication>
K
User avatar
Ats
Posts: 927
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: I need help with ZGEBullet zbtCreateHeightfieldTerrainShape

Post by Ats »

Thanks for your help. The 0.5-scaled MeshBox is a nice trick. From your examples, I managed to rearrange ZGEBullet Demo 2.
In order to completely get rid of the RenderTransformGroup on the terrain mesh, while keeping it identical to the physical terrain, I also had to switch the order in the Terrain array, and recenter the mesh:

Code: Select all

// V.Y and V.Y are switched to avoid RenderTransformGroup Rotate.X = -0.25
V.X = x * scale - halfWidth;
V.Y = h * TerrainScale;
V.Z = y * scale - halfDepth;

// Storage in Terrain array is switched to avoid RenderTransformGroup Rotate.Y = -0.25
Terrain[y, x] = h;
Now I can set the terrain scale simply by changing int TerrainScale = 20;.
I tried to do the same with the number of vertices by making everything depend on the size of the Terrain array, but something is still broken somewhere… I’ll continue tomorrow.

Code: Select all

<?xml version="1.0" encoding="iso-8859-1" ?>
<ZApplication Name="App" Comment="ZgeBullet demo #2. Created by Rado1" Caption="Physics Demo 2" ClearColor="0 0 0 1" AmbientLightColor="0.6353 0.6353 0.6353 1" FrameRateStyle="1" ScreenMode="0" CameraPosition="-79.8822 30 -4.3393" CameraRotation="0.05 1.2586 0" LightPosition="0 0 0" ViewportRatio="3" CustomViewportRatio="1.6667" ClipFar="800" MouseVisible="255" FileVersion="2" AndroidPackageName="com.rado1.PhysicsDemo2">
  <OnLoaded>
    <ZExternalLibrary Comment="Bullet 3D physics" ModuleName="ZgeBullet_x64" CallingConvention="1" BeforeInitExp="if(ANDROID) this.ModuleName = &quot;./libZgeBullet.so&quot;;">
      <Source>
<![CDATA[/*
  ZgeBullet Library, a wrapper for the Bullet Physics Library.
  http://bulletphysics.org

  Project home
  https://github.com/Rado-1/ZgeBullet

  Download Windows DLL and Android shared library from
  https://github.com/Rado-1/ZgeBullet/releases

  Copyright (c) 2012-2015 Radovan Cervenka

  Version: 2.1 (2015-06-27)
*/


// Constants

// Triangle mesh types
const int ZBT_TRIANGLE_CONVEX_HULL_MESH = 1;
const int ZBT_TRIANGLE_CONCAVE_STATIC_MESH = 2;
const int ZBT_TRIANGLE_CONCAVE_DEFORMABLE_MESH = 3;

// Activation states
const int ZBT_ACTIVE_TAG = 1;
const int ZBT_ISLAND_SLEEPING = 2;
const int ZBT_WANTS_DEACTIVATION = 3;
const int ZBT_DISABLE_DEACTIVATION = 4;
const int ZBT_DISABLE_SIMULATION = 5;

// Default values of constraint limits
const float ZBT_DEFAULT_HINGE_SOFTNESS = 0.9;
const float ZBT_DEFAULT_HINGE_BIAS_FACTOR = 0.3;
const float ZBT_DEFAULT_HINGE_RELAXATION_FACTOR = 1.0;
const float ZBT_DEFAULT_CONE_TWIST_SOFTNESS = 1.0;
const float ZBT_DEFAULT_CONE_TWIST_BIAS_FACTOR = 0.3;
const float ZBT_DEFAULT_CONE_TWIST_RELAXATION_FACTOR = 1.0;

// Vehicle tunning defaults
const float ZBT_DEFAULT_VEHICLE_SUSP_STIFFNESS = 5.88;
const float ZBT_DEFAULT_VEHICLE_SUSP_COMPRESSION = 0.83;
const float ZBT_DEFAULT_VEHICLE_SUSP_DAMPING = 0.88;
const float ZBT_DEFAULT_VEHICLE_SUSP_MAX_SUSP_TRAVEL_CM = 500.0;
const float ZBT_DEFAULT_VEHICLE_SUSP_FORCE = 6000.0;
const float ZBT_DEFAULT_VEHICLE_FRICTION_SLIP = 10.5;

// Axes
const int ZBT_AXIS_X_LINEAR = 0;
const int ZBT_AXIS_Y_LINEAR = 1;
const int ZBT_AXIS_Z_LINEAR = 2;
const int ZBT_AXIS_X_ANGULAR = 3;
const int ZBT_AXIS_Y_ANGULAR = 4;
const int ZBT_AXIS_Z_ANGULAR = 5;

// Collision flags
const int ZBT_CF_STATIC_OBJECT= 1;
const int ZBT_CF_KINEMATIC_OBJECT= 2;
const int ZBT_CF_NO_CONTACT_RESPONSE = 4;
const int ZBT_CF_CUSTOM_MATERIAL_CALLBACK = 8;
const int ZBT_CF_CHARACTER_OBJECT = 16;
const int ZBT_CF_DISABLE_SPU_COLLISION_PROCESSING = 64;


// Functions


// World

xptr zbtCreateWorld() {}

void zbtDestroyWorld(xptr world) {}

void zbtSetCurrentWorld(xptr world) {}

void zbtSetWorldGravity(float x, float y, float z) {}

void zbtStepSimulation(float timeStep, int maxSubSteps, float fixedTimeStep) {}


// Collision shapes
xptr zbtCreateStaticPlaneShape(
	float normalX, float normalY, float normalZ, float planeConstant) {}

xptr zbtCreateBoxShape(float x, float y, float z) {}

xptr zbtCreateSphereShape(float radius) {}

xptr zbtCreateScalableSphereShape(float radius) {}

xptr zbtCreateConeShape(float radius, float height) {}

xptr zbtCreateCylinderShape(float radius, float height) {}

xptr zbtCreateCapsuleShape(float radius, float height) {}

xptr zbtCreateCompoundShape() {}

xptr zbtAddChildShape(xptr compoundShape, xptr childShape,
	float x, float y, float z, float rx, float ry, float rz) {}

xptr zbtRemoveChildShape(xptr compoundShape, xptr childShape) {}

xptr zbtCreateHeightfieldTerrainShape(xptr heightfieldData,
	int width, int length, float minHeight, float maxHeight, int upAxis,
	int bFlipQuadEdges, int bDiamondSubdivision) {}

xptr zbtCreateConvexHullShape(xptr points, int numPoints) {}

xptr zbtCreateMultiSphereShape(xptr positions, xptr radii, int numSpheres) {}

xptr zbtCreateTriangleMeshShape(xptr triangles, int numTriangles, int meshType) {}

void zbtUpdateDeformableTriangleMesh(xptr triangleMeshShape) {}

void zbtSetShapeLocalScaling(xptr shape, float x, float y, float z) {}

void zbtSetShapeMargin(xptr shape, float margin) {}

void zbtDeleteShape(xptr shape) {}

void zbtDeleteAllShapes() {}


// Rigid bodies

xptr zbtCreateRigidBodyXYZ(float mass, xptr shape,
	float x, float y, float z, float rx, float ry, float rz) {}

xptr zbtCreateRigidBody(float mass, xptr shape, xptr position, xptr rotation) {}

void zbtDeleteRigidBody(xptr rigidBody) {}

void zbtSetMass(xptr rigidBody, float mass) {}

void zbtSetDamping(xptr rigidBody, float linearDamping, float angularDamping) {}

void zbtSetLinearFactor(xptr rigidBody, float x, float y, float z) {}

void zbtSetAngularFactor(xptr rigidBody, float x, float y, float z) {}

void zbtSetGravity(xptr rigidBody, float x, float y, float z) {}

void zbtSetLinearVelocity(xptr rigidBody, float x, float y, float z) {}

void zbtGetLinearVelocity(xptr rigidBody,
	ref float outX, ref float outY, ref float outZ) {}

void zbtSetAngularVelocity(xptr rigidBody, float x, float y, float z) {}

void zbtGetAngularVelocity(xptr rigidBody,
	ref float outX, ref float outY, ref float outZ) {}

void zbtApplyCentralImpulse(xptr rigidBody, float x, float y, float z) {}

void zbtApplyTorqueImpulse(xptr rigidBody, float x, float y, float z) {}

void zbtApplyImpulse(xptr rigidBody, float x, float y, float z,
	float relX, float relY, float relZ) {}

void zbtSetSleepingThresholds(xptr rigidBody, float linear, float angular) {}


// Constraints and limits

int zbtAreConnected(xptr rigidBodyA, xptr rigidBodyB) {}

xptr zbtAddFixedConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz,
	float rotAx, float rotAy, float rotAz,
	float rotBx, float rotBy, float rotBz, int bDisableCollision) {}

xptr zbtAddPoint2PointConstraint1(xptr rigidBody,
	float pivotX, float pivotY, float pivotZ) {}

xptr zbtAddPoint2PointConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz, int bDisableCollision) {}

xptr zbtAddHingeConstraint1(xptr rigidBody,
	float pivotX, float pivotY, float pivotZ,
	float axisX, float axisY, float axisZ) {}

xptr zbtAddHingeConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz,
	float axisAx, float axisAy, float axisAz,
	float axisBx, float axisBy, float axisBz, int bDisableCollision) {}

void zbtSetHingeLimits(xptr hinge, float low, float high,
	float softness, float biasFactor, float relaxationFactor) {}

void zbtEnableHingeAngularMotor(xptr hinge, int bEnableMotor,
	float targetVelocity, float maxMotorImpulse) {}

xptr zbtAddConeTwistConstraint1(xptr rigidBody,
	float pivotX, float pivotY, float pivotZ,
	float rotX, float rotY, float rotZ) {}

xptr zbtAddConeTwistConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz,
	float rotAx, float rotAy, float rotAz,
	float rotBx, float rotBy, float rotBz, int bDisableCollision) {}

void zbtSetConeTwistLimits(xptr twist, float swingSpanA, float swingSpanB,
	float twistSpan, float damping, float softness, float biasFactor,
	float relaxationFactor) {}

void zbtEnableConeTwistMotor(xptr twist,
	int bEnableMotor, float maxMotorImpulse,
	float targetX, float targetY, float targetZ) {}

xptr zbtAddSliderConstraint1(xptr rigidBody,
	float pivotX, float pivotY, float pivotZ,
	float rotX, float rotY, float rotZ,
	int bUseLinearReferenceWorldFrame) {}

xptr zbtAddSliderConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz,
	float rotAx, float rotAy, float rotAz,
	float rotBx, float rotBy, float rotBz,
	int bUseLinearReferenceFrameA, int bDisableCollision) {}

void zbtSetSliderLimits(xptr slider,
	float linLower, float linUpper, float angLower, float angUpper) {}

void zbtSetSliderSoftness(xptr slider,
	float dirLin, float dirAng, float limLin, float limAng,
	float orthoLin, float orthoAng) {}

void zbtSetSliderRestitution(xptr slider,
	float dirLin, float dirAng, float limLin, float limAng,
	float orthoLin, float orthoAng) {}

void zbtSetSliderDamping(xptr slider,
	float dirLin, float dirAng, float limLin, float limAng,
	float orthoLin, float orthoAng) {}

void zbtEnableSliderLinearMotor(xptr slider, int bEnableMotor,
	float targetVelocity, float maxForce) {}

void zbtEnableSliderAngularMotor(xptr slider, int bEnableMotor,
	float targetVelocity, float maxForce) {}

xptr zbtAddGearConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float axisAx, float axisAy, float axisAz,
	float axisBx, float axisBy, float axisBz,
	float ratio) {}

void zbtSetGearConstraint(xptr gear,
	float axisAx, float axisAy, float axisAz,
	float axisBx, float axisBy, float axisBz,
	float ratio) {}

xptr zbtAddGeneric6DofConstraint1(xptr rigidBody,
	float pivotX, float pivotY, float pivotZ,
	float rotX, float rotY, float rotZ,
	int bUseLinearReferenceWorldFrame) {}

xptr zbtAddGeneric6DofConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz,
	float rotAx, float rotAy, float rotAz,
	float rotBx, float rotBy, float rotBz,
	int bUseLinearReferenceFrameA, int bDisableCollision) {}

void zbtSetGeneric6DofLimits(xptr dof, int axis, float lower, float upper) {}

void zbtSetGeneric6DofLinearLimits(xptr dof,
	float lowerX, float lowerY, float lowerZ,
	float upperX, float upperY, float upperZ) {}

void zbtSetGeneric6DofAngularLimits(xptr dof,
	float lowerX, float lowerY, float lowerZ,
	float upperX, float upperY, float upperZ) {}

xptr zbtAddGeneric6DofSpringConstraint1(xptr rigidBody,
	float pivotX, float pivotY, float pivotZ,
	float rotX, float rotY, float rotZ,
	int bUseLinearReferenceWorldFrame) {}

xptr zbtAddGeneric6DofSpringConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz,
	float rotAx, float rotAy, float rotAz,
	float rotBx, float rotBy, float rotBz,
	int bUseLinearReferenceFrameA, int bDisableCollision) {}

void zbtSetGeneric6DofSpring(xptr spring,
	int axis, int bEnableSpring, float stiffness, float damping,
	float equilibriumPoint) {}

void zbtSetEnabled(xptr constraint, int bEnabled) {}

void zbtDeleteConstraint(xptr constraint) {}


// Raycast vehicle

void zbtSetVehicleTunning(float suspStiffness, float suspCompression,
	float suspDamping, float maxSuspTravelCm, float maxSuspForce,
	float frictionSlip) {}

xptr zbtCreateRaycastVehicle(xptr carChassis,
	int rightAxis, int upAxis, int forwardAxis) {}

int zbtAddWheel(xptr vehicle,
	float connectionPointX, float connectionPointY, float connectionPointZ,
	float directionX, float directionY, float directionZ,
	float wheelAxleX, float wheelAxleY, float wheelAxleZ,
	float wheelRadius, float suspRestLength, int bIsFrontWheel) {}

void zbtSetWheelIsFront(xptr vehicle, int wheelId, int bIsFront) {}

void zbtSetWheelRadius(xptr vehicle, int wheelId, float radius) {}

void zbtSetWheelRollInfluence(xptr vehicle, int wheelId, float rollInfluence) {}

void zbtSetWheelFrictionSlip(xptr vehicle, int wheelId, float frictionSlip) {}

void zbtSetWheelSuspRestLength(xptr vehicle, int wheelId, float suspRestLength) {}

void zbtSetWheelMaxSuspTravel(xptr vehicle, int wheelId, float maxSuspTravel) {}

void zbtSetWheelSuspStiffness(xptr vehicle, int wheelId, float suspStiffness) {}

void zbtSetWheelDampingCompression(xptr vehicle, int wheelId,
	float dampingCompression) {}

void zbtSetWheelDampingRelaxation(xptr vehicle, int wheelId,
	float dampingRelaxation) {}

void zbtSetWheelSteering(xptr vehicle, int wheelId, float steering) {}

void zbtSetWheelEngineForce(xptr vehicle, int wheelId, float force) {}

void zbtSetWheelBrake(xptr vehicle, int wheelId, float brake) {}

void zbtResetVehicleSusp(xptr vehicle) {}

float zbtGetVehicleCurrentSpeed(xptr vehicle) {}

void zbtGetWheelPositionXYZ(xptr vehicle, int wheelId,
	ref float outX, ref float outY, ref float outZ) {}

void zbtGetWheelPosition(xptr vehicle, int wheelId, xptr outPosition) {}

void zbtGetWheelRotationXYZ(xptr vehicle, int wheelId,
	ref float outRx, ref float outRy, ref float outRz) {}

void zbtGetWheelRotation(xptr vehicle, int wheelId, xptr outRotation) {}

void zbtGetWheelPosRotXYZ(xptr vehicle, int wheelId,
	ref float outX, ref float outY, ref float outZ,
	ref float outRx, ref float outRy, ref float outRz) {}

void zbtGetWheelPosRot(xptr vehicle, int wheelId,
	xptr outPosition, xptr outRotation) {}

void zbtDeleteRaycastVehicle(xptr vehicle) {}


// Ghost object

xptr zbtCreateGhostObject(xptr shape,
	float x, float y, float z, float rx, float ry, float rz) {}

void zbtDeleteGhostObject(xptr ghostObject) {}

int zbtGetNumOverlappingObjects(xptr ghostObject) {}

xptr zbtGetOverlappingObject(xptr ghostObject, int index) {}


// Kinematic character controller

xptr zbtCreateKinematicCharacterController(
	xptr ghostObject, float stepHeight) {}

void zbtDeleteKinematicCharacterController(xptr controller) {}

void zbtSetCharacterUpAxis(xptr controller, int axis) {}

void zbtSetCharacterWalkDirection(xptr controller,
	float x, float y, float z) {}

void zbtSetCharacterVelocityForTimeInterval(xptr controller,
	float x, float y, float z, float timeInterval) {}

void zbtCharacterWarp(xptr controller, float x, float y, float z) {}

void zbtSetCharacterFallSpeed(xptr controller, float fallSpeed) {}

void zbtSetCharacterJumpSpeed(xptr controller, float jumpSpeed) {}

void zbtSetCharacterMaxJumpHeight(xptr controller, float maxJumpHeight) {}

int zbtCharacterCanJump(xptr controller) {}

void zbtCharacterJump(xptr controller) {}

void zbtSetCharacterGravity(xptr controller, float gravity) {}

void zbtSetCharacterMaxSlope(xptr controller, float slope) {}

void zbtSetCharacterUseGhostSweepTest(xptr controller,
	int bUseGhostObjectSweepTest) {}

int zbtCharacterOnGround(xptr controller) {}

void zbtCharacterReset(xptr controller) {}

void zbtSetCharacterUpInterpolate(xptr controller, int bInterpolate) {}


// Collision objects (in general)

void zbtSetFriction(xptr obj, float friction) {}

void zbtSetRestitution(xptr obj, float restitution) {}

void zbtSetHitFraction(xptr obj, float hitFraction) {}

void zbtGetPositionXYZ(xptr obj,
	ref float outX, ref float outY, ref float outZ) {}

void zbtGetPosition(xptr obj, xptr outPosition) {}

void zbtSetPositionXYZ(xptr obj, float x, float y, float z) {}

void zbtSetPosition(xptr obj, xptr position) {}

void zbtGetRotationXYZ(xptr obj,
	ref float outRx, ref float outRy, ref float outRz) {}

void zbtGetRotation(xptr obj, xptr outRotation) {}

void zbtSetRotationXYZ(xptr obj, float rx, float ry, float rz) {}

void zbtSetRotation(xptr obj, xptr rotation) {}

void zbtGetPosRotXYZ(xptr obj,
	ref float outX, ref float outY, ref float outZ,
	ref float outRx, ref float outRy, ref float outRz) {}

void zbtGetPosRot(xptr obj, xptr outPosition, xptr outRotation) {}

void zbtSetPosRotXYZ(xptr obj,
	float x, float y, float z,
	float rx, float ry, float rz) {}

void zbtSetPosRot(xptr obj, xptr position, xptr rotation) {}

void zbtSetCollisionFlags(xptr obj, int flags) {}

int zbtIsActive(xptr obj) {}

void zbtActivate(xptr obj, int bForceActivation) {}

void zbtSetActivationState(xptr obj, int newState) {}

void zbtForceActivationState(xptr obj, int newState) {}

void zbtSetDeactivationTime(xptr obj, float time) {}

void zbtSetUserIndex(xptr obj, int index) {}

int zbtGetUserIndex(xptr obj) {}

void zbtSetUserModel(xptr obj, model userModel) {}

model zbtGetUserModel(xptr obj) {}


// Collision detection

void zbtSetIgnoreCollisionCheck(xptr objA, xptr objB,
	int bIgnoreCollisionCheck) {}

int zbtStartCollisionDetection() {}

int zbtGetNextContact(xptr outObjA, xptr outObjB,
	xptr outPosA, xptr outPosB, xptr outNormal) {}

void zbtGetCollidedObjects(int contactIndex, xptr outObjA, xptr outObjB) {}

int zbtIsColliding(xptr obj) {}

int zbtGetNumberOfCollisions(xptr obj) {}

int zbtIsCollidedWith(xptr objA, xptr objB) {}


// Raycasting

xptr zbtRayTest(float fromX, float fromY, float fromZ, float toX, float toY, float toZ) {}

void zbtGetRayTestHitPointXYZ(ref float outX, ref float outY, ref float outZ) {}

void zbtGetRayTestHitPoint(xptr outPosition) {}

void zbtGetRayTestHitNormalXYZ(ref float outX, ref float outY, ref float outZ) {}

void zbtGetRayTestHitNormal(xptr outNormal) {}]]>
      </Source>
    </ZExternalLibrary>
    <ZLibrary Comment="Globals" HasInitializer="1">
      <Source>
<![CDATA[// CONSTANTS

// boolean
const int FALSE = 0;
const int TRUE = 1;

// goniometric
const float PIx2 = PI * 2.0;
const float ROT90 = 0.25;

// VARIABLES

xptr World;
xptr SphereShape;

float TerrainGenOffset;
float[10,10] Terrain;
int TerrainScale = 20;]]>
      </Source>
    </ZLibrary>
    <ZExpression Comment="Init">
      <Expression>
<![CDATA[// init random seed
setRandomSeed(getSystemTime());

// init physical world
World = zbtCreateWorld();
zbtSetCurrentWorld(World);
zbtSetWorldGravity(0, -10, 0);

// create sphere collision shape
SphereShape = zbtCreateSphereShape(1.0);

// create terrain
Terrain_MeshBox.XCount = Terrain.SizeDim1 - 2;
Terrain_MeshBox.YCount = Terrain.SizeDim2 - 2;
@RefreshContent(Component: TerrainMesh);

xptr sh = zbtCreateHeightfieldTerrainShape(Terrain, Terrain.SizeDim1, Terrain.SizeDim2, -2, 2, ZBT_AXIS_Y_LINEAR, FALSE, FALSE);
zbtSetShapeLocalScaling(sh, TerrainScale - 1, TerrainScale, TerrainScale - 1);
xptr rb = zbtCreateRigidBodyXYZ(0, sh, 0, 0, 0, 0, 0, 0);
zbtSetFriction(rb, 1);]]>
      </Expression>
    </ZExpression>
  </OnLoaded>
  <OnUpdate>
    <ZExpression Comment="Update simulation and rotate camera">
      <Expression>
<![CDATA[// simulation step
float t = App.DeltaTime;
zbtStepSimulation(t, 3, t/2);

// Update terrain geometry
TerrainGenOffset += App.DeltaTime / 4;
@RefreshContent(Component: TerrainMesh);

// rotate camera
t = App.Time / 30;
App.CameraPosition.X = cos(t * PIx2) * 80;
App.CameraPosition.Z = sin(t * PIx2) * 80;
App.CameraRotation.Y = t - ROT90;]]>
      </Expression>
    </ZExpression>
    <Timer Comment="Spawn spheres" Interval="0.5">
      <OnTimer>
        <SpawnModel Model="SphereModel"/>
      </OnTimer>
    </Timer>
    <KeyPress Comment="Space - remove spheres" Keys=" " RepeatDelay="0.5">
      <OnPressed>
        <RemoveAllModels OfType="SphereModel"/>
      </OnPressed>
    </KeyPress>
  </OnUpdate>
  <OnRender>
    <RenderTransformGroup Comment="Sky" Scale="150 100 150" Translate="0 15 0">
      <Children>
        <UseMaterial Material="SkyMaterial"/>
        <RenderMesh Mesh="SphereMesh"/>
      </Children>
    </RenderTransformGroup>
    <UseMaterial Material="TerrainMaterial"/>
    <RenderMesh Mesh="TerrainMesh"/>
  </OnRender>
  <OnClose>
    <ZExpression Comment="Destroy physical world" Expression="zbtDestroyWorld(World);"/>
  </OnClose>
  <Lights>
    <Light Position="20 50 20" Color="1 1 0 1" SpotDirection="0 -1 0" SpotCutoff="0"/>
  </Lights>
  <Content>
    <Mesh Name="TerrainMesh">
      <Producers>
        <MeshBox Name="Terrain_MeshBox" Scale="0.5 0.5 1" XCount="8" YCount="8" Grid2DOnly="255"/>
        <MeshExpression VertexColors="255">
          <Expression>
<![CDATA[//

byte gridSizeX = Terrain.SizeDim1;
byte gridSizeY = Terrain.SizeDim2;

float x = round((V.X + 0.5) * (gridSizeX - 1)); // V.X = [-0.5, 0.5[ so x = [0, 9[
float y = round((0.5 - V.Y) * (gridSizeX - 1));

//float h = rnd();
float h = noise3(v.X*2, v.Y*2, TerrainGenOffset) * 2.5 + 0.6;

int scale = TerrainScale - 1;

float halfWidth  = (gridSizeX - 1) * scale * 0.5;
float halfDepth  = (gridSizeY - 1) * scale * 0.5;

// V.Y and V.Y are switched to avoid
// RenderTransformGroup Rotate.X = -0.25
V.X = x * scale - halfWidth;
V.Y = h * TerrainScale;
V.Z = y * scale - halfDepth;

// Storage in Terrain array is switched to avoid
// RenderTransformGroup Rotate.Y = -0.25
Terrain[y, x] = h;

// Colors
c.R = h+0.5;
c.G = h/2;
c.B = 0;]]>
          </Expression>
        </MeshExpression>
      </Producers>
    </Mesh>
    <Model Name="SphereModel" Position="-33.7846 3.3394 11.3442" Category="1" RenderOrder="1">
      <Definitions>
        <Variable Name="Sphere" Type="9"/>
      </Definitions>
      <OnSpawn>
        <ZExpression Comment="Init">
          <Expression>
<![CDATA[// create rigid body
Sphere = zbtCreateRigidBodyXYZ(0.1, SphereShape, 0, 20, 0, 0, 0, 0);

// set physical properties
zbtSetDamping(Sphere, 0.1, 0.1);
//zbtSetActivationState(rbId, TRUE);
zbtSetSleepingThresholds(Sphere, 0, 0);
zbtSetLinearVelocity(Sphere, random(0,9), 0, random(0,9));
zbtSetAngularVelocity(Sphere, random(0,1), random(0,1), random(0,1));

// set color
SphereColor.Color.R = rnd() + 0.1;
SphereColor.Color.G = rnd() + 0.1;
SphereColor.Color.B = rnd() + 0.1;]]>
          </Expression>
        </ZExpression>
      </OnSpawn>
      <OnUpdate>
        <ZExpression Comment="Update position and rotation">
          <Expression>
<![CDATA[zbtGetPosRot(Sphere, CurrentModel.Position, CurrentModel.Rotation);

if (CurrentModel.Position.Y < -3) @RemoveModel(Model:CurrentModel);]]>
          </Expression>
        </ZExpression>
      </OnUpdate>
      <OnRender>
        <UseMaterial Material="ObjectMaterial"/>
        <RenderSetColor Name="SphereColor" Color="0.9404 0.2947 0.476 1"/>
        <RenderMesh Mesh="SphereMesh"/>
      </OnRender>
      <OnRemove>
        <ZExpression Comment="Delete rigid body and shape" Expression="zbtDeleteRigidBody(Sphere);"/>
      </OnRemove>
    </Model>
    <Mesh Name="SphereMesh">
      <Producers>
        <MeshBox Scale="1 0.5 1" XCount="18" YCount="12" Grid2DOnly="255"/>
        <MeshExpression AutoNormals="0">
          <Expression>
<![CDATA[//

        float E, A, CO, X, Y, Z;

        // Convert range to radians

        E = v.Y*PI; // Elevation
        A = v.X*PI; // Azimuth

        // Convert spherical coordinates into cartesian

        CO = cos(E);

        X = sin(A)*CO;
        Y = sin(E);
        Z = cos(A)*CO;

        // Assign coordinates

        v.X = X;
        v.Y = Y;
        v.Z = Z;

        n.X = X;
        n.Y = Y;
        n.Z = Z;]]>
          </Expression>
        </MeshExpression>
      </Producers>
    </Mesh>
    <Group Comment="Bitmaps and Materials">
      <Children>
        <Material Name="ObjectMaterial" WireframeWidth="0" SpecularColor="0 0 0 1" EmissionColor="0 0 0 1"/>
        <Bitmap Name="TerrainBitmap" Width="16" Height="16" Filter="2">
          <Producers>
            <BitmapExpression UseBlankSource="1">
              <Expression>
<![CDATA[Pixel.R = x > 0.9 || y > 0.9 ? 0 :1;
Pixel.G = Pixel.R;
Pixel.B = Pixel.R;]]>
              </Expression>
            </BitmapExpression>
          </Producers>
        </Bitmap>
        <Material Name="TerrainMaterial" Color="1 1 1 0.5" SpecularColor="0 0 0 1" EmissionColor="0 0 0 1" DrawBackFace="255">
          <Textures>
            <MaterialTexture Texture="TerrainBitmap" TextureScale="100 100 1" TextureWrapMode="1" TexCoords="1"/>
          </Textures>
        </Material>
        <Bitmap Name="SkyBitmap" Width="16" Height="128" Filter="2">
          <Producers>
            <BitmapExpression>
              <Expression>
<![CDATA[float t;

// Symmetric gradient: 0 at middle, 1 at top and bottom
t = abs(Y - 0.5) * 2;

// Top & Bottom color (25, 51, 255) -> normalized
float r1 = 0.1;
float g1 = 0.2;
float b1 = 1;

// Middle color (0, 227, 230) -> normalized
float r2 = 0;
float g2 = 0.89;
float b2 = 0.9;

// Linear interpolation
Pixel.R = r2 * (1.0 - t) + r1 * t;
Pixel.G = g2 * (1.0 - t) + g1 * t;
Pixel.B = b2 * (1.0 - t) + b1 * t;]]>
              </Expression>
            </BitmapExpression>
          </Producers>
        </Bitmap>
        <Material Name="SkyMaterial" WireframeWidth="0" Light="0" SpecularColor="0 0 0 1" EmissionColor="0 0 0 1" DrawBackFace="255">
          <Textures>
            <MaterialTexture Texture="SkyBitmap" TextureScale="1 1 0" TextureY="0.1" TexCoords="1" Origin="0 0 0"/>
          </Textures>
        </Material>
      </Children>
    </Group>
  </Content>
</ZApplication>
By te way, I replaced the sky bitmap with the exact same gradient produced by LLM. Worked like a charm.
User avatar
VilleK
Site Admin
Posts: 2414
Joined: Mon Jan 15, 2007 4:50 pm
Location: Stockholm, Sweden
Contact:

Re: I need help with ZGEBullet zbtCreateHeightfieldTerrainShape

Post by VilleK »

Ats wrote: Sun Dec 07, 2025 11:43 pm By te way, I replaced the sky bitmap with the exact same gradient produced by LLM. Worked like a charm.
So you mean you showed the LLM the bitmap file and asked it to write code to generate it? That is a interesting form of compression.
User avatar
Kjell
Posts: 1980
Joined: Sat Feb 23, 2008 11:15 pm

Re: I need help with ZGEBullet zbtCreateHeightfieldTerrainShape

Post by Kjell »

Hi Ats,
Ats wrote: Sun Dec 07, 2025 11:43 pmsomething is still broken somewhere…
Just a wild guess .. but in case the collision seems slightly off sometimes, it's probably because Bullet interprets the heightfield values differently from the mesh that you end up with when using a Grid2DOnly MeshBox.

Image

Both meshes use the exact same values, but in the bottom version the faces are split over the diagonal that has the smallest difference in height.

Still think it would be convenient to have a TerrainMesh component for this :wink:

K
User avatar
Ats
Posts: 927
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: I need help with ZGEBullet zbtCreateHeightfieldTerrainShape

Post by Ats »

Oh, you're right. But that's not a problem for me, as the terrain is supposed to be water :lol:

Here's my last modification:

Code: Select all

<?xml version="1.0" encoding="iso-8859-1" ?>
<ZApplication Name="App" Comment="ZgeBullet demo #2. Created by Rado1" Caption="Physics Demo 2" ClearColor="0 0 0 1" AmbientLightColor="0.6353 0.6353 0.6353 1" FrameRateStyle="1" ScreenMode="0" CameraPosition="78.3386 30 16.2191" CameraRotation="0.05 -0.2175 0" LightPosition="0 0 0" ViewportRatio="3" CustomViewportRatio="1.6667" ClipFar="800" MouseVisible="255" FileVersion="2" AndroidPackageName="com.rado1.PhysicsDemo2">
  <OnLoaded>
    <ZExternalLibrary Comment="Bullet 3D physics" ModuleName="ZgeBullet_x64" CallingConvention="1" BeforeInitExp="if(ANDROID) this.ModuleName = &quot;./libZgeBullet.so&quot;;">
      <Source>
<![CDATA[/*
  ZgeBullet Library, a wrapper for the Bullet Physics Library.
  http://bulletphysics.org

  Project home
  https://github.com/Rado-1/ZgeBullet

  Download Windows DLL and Android shared library from
  https://github.com/Rado-1/ZgeBullet/releases

  Copyright (c) 2012-2015 Radovan Cervenka

  Version: 2.1 (2015-06-27)
*/


// Constants

// Triangle mesh types
const int ZBT_TRIANGLE_CONVEX_HULL_MESH = 1;
const int ZBT_TRIANGLE_CONCAVE_STATIC_MESH = 2;
const int ZBT_TRIANGLE_CONCAVE_DEFORMABLE_MESH = 3;

// Activation states
const int ZBT_ACTIVE_TAG = 1;
const int ZBT_ISLAND_SLEEPING = 2;
const int ZBT_WANTS_DEACTIVATION = 3;
const int ZBT_DISABLE_DEACTIVATION = 4;
const int ZBT_DISABLE_SIMULATION = 5;

// Default values of constraint limits
const float ZBT_DEFAULT_HINGE_SOFTNESS = 0.9;
const float ZBT_DEFAULT_HINGE_BIAS_FACTOR = 0.3;
const float ZBT_DEFAULT_HINGE_RELAXATION_FACTOR = 1.0;
const float ZBT_DEFAULT_CONE_TWIST_SOFTNESS = 1.0;
const float ZBT_DEFAULT_CONE_TWIST_BIAS_FACTOR = 0.3;
const float ZBT_DEFAULT_CONE_TWIST_RELAXATION_FACTOR = 1.0;

// Vehicle tunning defaults
const float ZBT_DEFAULT_VEHICLE_SUSP_STIFFNESS = 5.88;
const float ZBT_DEFAULT_VEHICLE_SUSP_COMPRESSION = 0.83;
const float ZBT_DEFAULT_VEHICLE_SUSP_DAMPING = 0.88;
const float ZBT_DEFAULT_VEHICLE_SUSP_MAX_SUSP_TRAVEL_CM = 500.0;
const float ZBT_DEFAULT_VEHICLE_SUSP_FORCE = 6000.0;
const float ZBT_DEFAULT_VEHICLE_FRICTION_SLIP = 10.5;

// Axes
const int ZBT_AXIS_X_LINEAR = 0;
const int ZBT_AXIS_Y_LINEAR = 1;
const int ZBT_AXIS_Z_LINEAR = 2;
const int ZBT_AXIS_X_ANGULAR = 3;
const int ZBT_AXIS_Y_ANGULAR = 4;
const int ZBT_AXIS_Z_ANGULAR = 5;

// Collision flags
const int ZBT_CF_STATIC_OBJECT= 1;
const int ZBT_CF_KINEMATIC_OBJECT= 2;
const int ZBT_CF_NO_CONTACT_RESPONSE = 4;
const int ZBT_CF_CUSTOM_MATERIAL_CALLBACK = 8;
const int ZBT_CF_CHARACTER_OBJECT = 16;
const int ZBT_CF_DISABLE_SPU_COLLISION_PROCESSING = 64;


// Functions


// World

xptr zbtCreateWorld() {}

void zbtDestroyWorld(xptr world) {}

void zbtSetCurrentWorld(xptr world) {}

void zbtSetWorldGravity(float x, float y, float z) {}

void zbtStepSimulation(float timeStep, int maxSubSteps, float fixedTimeStep) {}


// Collision shapes
xptr zbtCreateStaticPlaneShape(
	float normalX, float normalY, float normalZ, float planeConstant) {}

xptr zbtCreateBoxShape(float x, float y, float z) {}

xptr zbtCreateSphereShape(float radius) {}

xptr zbtCreateScalableSphereShape(float radius) {}

xptr zbtCreateConeShape(float radius, float height) {}

xptr zbtCreateCylinderShape(float radius, float height) {}

xptr zbtCreateCapsuleShape(float radius, float height) {}

xptr zbtCreateCompoundShape() {}

xptr zbtAddChildShape(xptr compoundShape, xptr childShape,
	float x, float y, float z, float rx, float ry, float rz) {}

xptr zbtRemoveChildShape(xptr compoundShape, xptr childShape) {}

xptr zbtCreateHeightfieldTerrainShape(xptr heightfieldData,
	int width, int length, float minHeight, float maxHeight, int upAxis,
	int bFlipQuadEdges, int bDiamondSubdivision) {}

xptr zbtCreateConvexHullShape(xptr points, int numPoints) {}

xptr zbtCreateMultiSphereShape(xptr positions, xptr radii, int numSpheres) {}

xptr zbtCreateTriangleMeshShape(xptr triangles, int numTriangles, int meshType) {}

void zbtUpdateDeformableTriangleMesh(xptr triangleMeshShape) {}

void zbtSetShapeLocalScaling(xptr shape, float x, float y, float z) {}

void zbtSetShapeMargin(xptr shape, float margin) {}

void zbtDeleteShape(xptr shape) {}

void zbtDeleteAllShapes() {}


// Rigid bodies

xptr zbtCreateRigidBodyXYZ(float mass, xptr shape,
	float x, float y, float z, float rx, float ry, float rz) {}

xptr zbtCreateRigidBody(float mass, xptr shape, xptr position, xptr rotation) {}

void zbtDeleteRigidBody(xptr rigidBody) {}

void zbtSetMass(xptr rigidBody, float mass) {}

void zbtSetDamping(xptr rigidBody, float linearDamping, float angularDamping) {}

void zbtSetLinearFactor(xptr rigidBody, float x, float y, float z) {}

void zbtSetAngularFactor(xptr rigidBody, float x, float y, float z) {}

void zbtSetGravity(xptr rigidBody, float x, float y, float z) {}

void zbtSetLinearVelocity(xptr rigidBody, float x, float y, float z) {}

void zbtGetLinearVelocity(xptr rigidBody,
	ref float outX, ref float outY, ref float outZ) {}

void zbtSetAngularVelocity(xptr rigidBody, float x, float y, float z) {}

void zbtGetAngularVelocity(xptr rigidBody,
	ref float outX, ref float outY, ref float outZ) {}

void zbtApplyCentralImpulse(xptr rigidBody, float x, float y, float z) {}

void zbtApplyTorqueImpulse(xptr rigidBody, float x, float y, float z) {}

void zbtApplyImpulse(xptr rigidBody, float x, float y, float z,
	float relX, float relY, float relZ) {}

void zbtSetSleepingThresholds(xptr rigidBody, float linear, float angular) {}


// Constraints and limits

int zbtAreConnected(xptr rigidBodyA, xptr rigidBodyB) {}

xptr zbtAddFixedConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz,
	float rotAx, float rotAy, float rotAz,
	float rotBx, float rotBy, float rotBz, int bDisableCollision) {}

xptr zbtAddPoint2PointConstraint1(xptr rigidBody,
	float pivotX, float pivotY, float pivotZ) {}

xptr zbtAddPoint2PointConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz, int bDisableCollision) {}

xptr zbtAddHingeConstraint1(xptr rigidBody,
	float pivotX, float pivotY, float pivotZ,
	float axisX, float axisY, float axisZ) {}

xptr zbtAddHingeConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz,
	float axisAx, float axisAy, float axisAz,
	float axisBx, float axisBy, float axisBz, int bDisableCollision) {}

void zbtSetHingeLimits(xptr hinge, float low, float high,
	float softness, float biasFactor, float relaxationFactor) {}

void zbtEnableHingeAngularMotor(xptr hinge, int bEnableMotor,
	float targetVelocity, float maxMotorImpulse) {}

xptr zbtAddConeTwistConstraint1(xptr rigidBody,
	float pivotX, float pivotY, float pivotZ,
	float rotX, float rotY, float rotZ) {}

xptr zbtAddConeTwistConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz,
	float rotAx, float rotAy, float rotAz,
	float rotBx, float rotBy, float rotBz, int bDisableCollision) {}

void zbtSetConeTwistLimits(xptr twist, float swingSpanA, float swingSpanB,
	float twistSpan, float damping, float softness, float biasFactor,
	float relaxationFactor) {}

void zbtEnableConeTwistMotor(xptr twist,
	int bEnableMotor, float maxMotorImpulse,
	float targetX, float targetY, float targetZ) {}

xptr zbtAddSliderConstraint1(xptr rigidBody,
	float pivotX, float pivotY, float pivotZ,
	float rotX, float rotY, float rotZ,
	int bUseLinearReferenceWorldFrame) {}

xptr zbtAddSliderConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz,
	float rotAx, float rotAy, float rotAz,
	float rotBx, float rotBy, float rotBz,
	int bUseLinearReferenceFrameA, int bDisableCollision) {}

void zbtSetSliderLimits(xptr slider,
	float linLower, float linUpper, float angLower, float angUpper) {}

void zbtSetSliderSoftness(xptr slider,
	float dirLin, float dirAng, float limLin, float limAng,
	float orthoLin, float orthoAng) {}

void zbtSetSliderRestitution(xptr slider,
	float dirLin, float dirAng, float limLin, float limAng,
	float orthoLin, float orthoAng) {}

void zbtSetSliderDamping(xptr slider,
	float dirLin, float dirAng, float limLin, float limAng,
	float orthoLin, float orthoAng) {}

void zbtEnableSliderLinearMotor(xptr slider, int bEnableMotor,
	float targetVelocity, float maxForce) {}

void zbtEnableSliderAngularMotor(xptr slider, int bEnableMotor,
	float targetVelocity, float maxForce) {}

xptr zbtAddGearConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float axisAx, float axisAy, float axisAz,
	float axisBx, float axisBy, float axisBz,
	float ratio) {}

void zbtSetGearConstraint(xptr gear,
	float axisAx, float axisAy, float axisAz,
	float axisBx, float axisBy, float axisBz,
	float ratio) {}

xptr zbtAddGeneric6DofConstraint1(xptr rigidBody,
	float pivotX, float pivotY, float pivotZ,
	float rotX, float rotY, float rotZ,
	int bUseLinearReferenceWorldFrame) {}

xptr zbtAddGeneric6DofConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz,
	float rotAx, float rotAy, float rotAz,
	float rotBx, float rotBy, float rotBz,
	int bUseLinearReferenceFrameA, int bDisableCollision) {}

void zbtSetGeneric6DofLimits(xptr dof, int axis, float lower, float upper) {}

void zbtSetGeneric6DofLinearLimits(xptr dof,
	float lowerX, float lowerY, float lowerZ,
	float upperX, float upperY, float upperZ) {}

void zbtSetGeneric6DofAngularLimits(xptr dof,
	float lowerX, float lowerY, float lowerZ,
	float upperX, float upperY, float upperZ) {}

xptr zbtAddGeneric6DofSpringConstraint1(xptr rigidBody,
	float pivotX, float pivotY, float pivotZ,
	float rotX, float rotY, float rotZ,
	int bUseLinearReferenceWorldFrame) {}

xptr zbtAddGeneric6DofSpringConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz,
	float rotAx, float rotAy, float rotAz,
	float rotBx, float rotBy, float rotBz,
	int bUseLinearReferenceFrameA, int bDisableCollision) {}

void zbtSetGeneric6DofSpring(xptr spring,
	int axis, int bEnableSpring, float stiffness, float damping,
	float equilibriumPoint) {}

void zbtSetEnabled(xptr constraint, int bEnabled) {}

void zbtDeleteConstraint(xptr constraint) {}


// Raycast vehicle

void zbtSetVehicleTunning(float suspStiffness, float suspCompression,
	float suspDamping, float maxSuspTravelCm, float maxSuspForce,
	float frictionSlip) {}

xptr zbtCreateRaycastVehicle(xptr carChassis,
	int rightAxis, int upAxis, int forwardAxis) {}

int zbtAddWheel(xptr vehicle,
	float connectionPointX, float connectionPointY, float connectionPointZ,
	float directionX, float directionY, float directionZ,
	float wheelAxleX, float wheelAxleY, float wheelAxleZ,
	float wheelRadius, float suspRestLength, int bIsFrontWheel) {}

void zbtSetWheelIsFront(xptr vehicle, int wheelId, int bIsFront) {}

void zbtSetWheelRadius(xptr vehicle, int wheelId, float radius) {}

void zbtSetWheelRollInfluence(xptr vehicle, int wheelId, float rollInfluence) {}

void zbtSetWheelFrictionSlip(xptr vehicle, int wheelId, float frictionSlip) {}

void zbtSetWheelSuspRestLength(xptr vehicle, int wheelId, float suspRestLength) {}

void zbtSetWheelMaxSuspTravel(xptr vehicle, int wheelId, float maxSuspTravel) {}

void zbtSetWheelSuspStiffness(xptr vehicle, int wheelId, float suspStiffness) {}

void zbtSetWheelDampingCompression(xptr vehicle, int wheelId,
	float dampingCompression) {}

void zbtSetWheelDampingRelaxation(xptr vehicle, int wheelId,
	float dampingRelaxation) {}

void zbtSetWheelSteering(xptr vehicle, int wheelId, float steering) {}

void zbtSetWheelEngineForce(xptr vehicle, int wheelId, float force) {}

void zbtSetWheelBrake(xptr vehicle, int wheelId, float brake) {}

void zbtResetVehicleSusp(xptr vehicle) {}

float zbtGetVehicleCurrentSpeed(xptr vehicle) {}

void zbtGetWheelPositionXYZ(xptr vehicle, int wheelId,
	ref float outX, ref float outY, ref float outZ) {}

void zbtGetWheelPosition(xptr vehicle, int wheelId, xptr outPosition) {}

void zbtGetWheelRotationXYZ(xptr vehicle, int wheelId,
	ref float outRx, ref float outRy, ref float outRz) {}

void zbtGetWheelRotation(xptr vehicle, int wheelId, xptr outRotation) {}

void zbtGetWheelPosRotXYZ(xptr vehicle, int wheelId,
	ref float outX, ref float outY, ref float outZ,
	ref float outRx, ref float outRy, ref float outRz) {}

void zbtGetWheelPosRot(xptr vehicle, int wheelId,
	xptr outPosition, xptr outRotation) {}

void zbtDeleteRaycastVehicle(xptr vehicle) {}


// Ghost object

xptr zbtCreateGhostObject(xptr shape,
	float x, float y, float z, float rx, float ry, float rz) {}

void zbtDeleteGhostObject(xptr ghostObject) {}

int zbtGetNumOverlappingObjects(xptr ghostObject) {}

xptr zbtGetOverlappingObject(xptr ghostObject, int index) {}


// Kinematic character controller

xptr zbtCreateKinematicCharacterController(
	xptr ghostObject, float stepHeight) {}

void zbtDeleteKinematicCharacterController(xptr controller) {}

void zbtSetCharacterUpAxis(xptr controller, int axis) {}

void zbtSetCharacterWalkDirection(xptr controller,
	float x, float y, float z) {}

void zbtSetCharacterVelocityForTimeInterval(xptr controller,
	float x, float y, float z, float timeInterval) {}

void zbtCharacterWarp(xptr controller, float x, float y, float z) {}

void zbtSetCharacterFallSpeed(xptr controller, float fallSpeed) {}

void zbtSetCharacterJumpSpeed(xptr controller, float jumpSpeed) {}

void zbtSetCharacterMaxJumpHeight(xptr controller, float maxJumpHeight) {}

int zbtCharacterCanJump(xptr controller) {}

void zbtCharacterJump(xptr controller) {}

void zbtSetCharacterGravity(xptr controller, float gravity) {}

void zbtSetCharacterMaxSlope(xptr controller, float slope) {}

void zbtSetCharacterUseGhostSweepTest(xptr controller,
	int bUseGhostObjectSweepTest) {}

int zbtCharacterOnGround(xptr controller) {}

void zbtCharacterReset(xptr controller) {}

void zbtSetCharacterUpInterpolate(xptr controller, int bInterpolate) {}


// Collision objects (in general)

void zbtSetFriction(xptr obj, float friction) {}

void zbtSetRestitution(xptr obj, float restitution) {}

void zbtSetHitFraction(xptr obj, float hitFraction) {}

void zbtGetPositionXYZ(xptr obj,
	ref float outX, ref float outY, ref float outZ) {}

void zbtGetPosition(xptr obj, xptr outPosition) {}

void zbtSetPositionXYZ(xptr obj, float x, float y, float z) {}

void zbtSetPosition(xptr obj, xptr position) {}

void zbtGetRotationXYZ(xptr obj,
	ref float outRx, ref float outRy, ref float outRz) {}

void zbtGetRotation(xptr obj, xptr outRotation) {}

void zbtSetRotationXYZ(xptr obj, float rx, float ry, float rz) {}

void zbtSetRotation(xptr obj, xptr rotation) {}

void zbtGetPosRotXYZ(xptr obj,
	ref float outX, ref float outY, ref float outZ,
	ref float outRx, ref float outRy, ref float outRz) {}

void zbtGetPosRot(xptr obj, xptr outPosition, xptr outRotation) {}

void zbtSetPosRotXYZ(xptr obj,
	float x, float y, float z,
	float rx, float ry, float rz) {}

void zbtSetPosRot(xptr obj, xptr position, xptr rotation) {}

void zbtSetCollisionFlags(xptr obj, int flags) {}

int zbtIsActive(xptr obj) {}

void zbtActivate(xptr obj, int bForceActivation) {}

void zbtSetActivationState(xptr obj, int newState) {}

void zbtForceActivationState(xptr obj, int newState) {}

void zbtSetDeactivationTime(xptr obj, float time) {}

void zbtSetUserIndex(xptr obj, int index) {}

int zbtGetUserIndex(xptr obj) {}

void zbtSetUserModel(xptr obj, model userModel) {}

model zbtGetUserModel(xptr obj) {}


// Collision detection

void zbtSetIgnoreCollisionCheck(xptr objA, xptr objB,
	int bIgnoreCollisionCheck) {}

int zbtStartCollisionDetection() {}

int zbtGetNextContact(xptr outObjA, xptr outObjB,
	xptr outPosA, xptr outPosB, xptr outNormal) {}

void zbtGetCollidedObjects(int contactIndex, xptr outObjA, xptr outObjB) {}

int zbtIsColliding(xptr obj) {}

int zbtGetNumberOfCollisions(xptr obj) {}

int zbtIsCollidedWith(xptr objA, xptr objB) {}


// Raycasting

xptr zbtRayTest(float fromX, float fromY, float fromZ, float toX, float toY, float toZ) {}

void zbtGetRayTestHitPointXYZ(ref float outX, ref float outY, ref float outZ) {}

void zbtGetRayTestHitPoint(xptr outPosition) {}

void zbtGetRayTestHitNormalXYZ(ref float outX, ref float outY, ref float outZ) {}

void zbtGetRayTestHitNormal(xptr outNormal) {}]]>
      </Source>
    </ZExternalLibrary>
    <ZLibrary Comment="Globals &amp; functions">
      <Source>
<![CDATA[// CONSTANTS

// boolean
const int FALSE = 0;
const int TRUE = 1;

// goniometric
const float PIx2 = PI * 2.0;
const float ROT90 = 0.25;

// VARIABLES

xptr World;
xptr SphereShape;


// Create Terrain

float[32, 32] Terrain;
byte TerrainScale, TerrainScaleHeight;
float TerrainGenOffset;

void createTerrain(byte xcount, byte ycount, byte scale, byte hscale)
{
  // Order is inverted in Terrain array to avoid visual Y rotate later on
  Terrain.SizeDim1 = ycount + 2;
  Terrain.SizeDim2 = xcount + 2;

  TerrainScale = scale;
  TerrainScaleHeight = hscale;

  // Generate Terrain Mesh
  Terrain_MeshBox.XCount = xcount;
  Terrain_MeshBox.YCount = ycount;
  @RefreshContent(Component: TerrainMesh);

  // Generate Terrain Physics
  xptr sh = zbtCreateHeightfieldTerrainShape(Terrain, Terrain.SizeDim1, Terrain.SizeDim2, -2, 2, ZBT_AXIS_Y_LINEAR, FALSE, FALSE);
  zbtSetShapeLocalScaling(sh, TerrainScale - 1, TerrainScaleHeight, TerrainScale - 1);
  xptr rb = zbtCreateRigidBodyXYZ(0, sh, 0, 0, 0, 0, 0, 0);
  zbtSetFriction(rb, 1);
}]]>
      </Source>
    </ZLibrary>
    <ZExpression Comment="Init">
      <Expression>
<![CDATA[// init random seed
setRandomSeed(getSystemTime());

// init physical world
World = zbtCreateWorld();
zbtSetCurrentWorld(World);
zbtSetWorldGravity(0, -10, 0);

// create sphere collision shape
SphereShape = zbtCreateSphereShape(1.0);

// create terrain: xcount, ycount, scale, height scale
createTerrain(30, 30, 4, 10);]]>
      </Expression>
    </ZExpression>
  </OnLoaded>
  <OnUpdate>
    <ZExpression Comment="Update simulation and rotate camera">
      <Expression>
<![CDATA[// simulation step
float t = App.DeltaTime;
zbtStepSimulation(t, 3, t/2);

// Update terrain geometry
TerrainGenOffset += App.DeltaTime / 4;
@RefreshContent(Component: TerrainMesh);

// rotate camera
t = App.Time / 30;
App.CameraPosition.X = cos(t * PIx2) * 80;
App.CameraPosition.Z = sin(t * PIx2) * 80;
App.CameraRotation.Y = t - ROT90;]]>
      </Expression>
    </ZExpression>
    <Timer Comment="Spawn spheres" Interval="0.5">
      <OnTimer>
        <SpawnModel Model="SphereModel"/>
      </OnTimer>
    </Timer>
    <KeyPress Comment="Space - remove spheres" Keys=" " RepeatDelay="0.5">
      <OnPressed>
        <RemoveAllModels OfType="SphereModel"/>
      </OnPressed>
    </KeyPress>
  </OnUpdate>
  <OnRender>
    <RenderTransformGroup Comment="Sky" Scale="150 100 150" Translate="0 15 0">
      <Children>
        <UseMaterial Material="SkyMaterial"/>
        <RenderMesh Mesh="SphereMesh"/>
      </Children>
    </RenderTransformGroup>
    <UseMaterial Material="TerrainMaterial"/>
    <RenderMesh Mesh="TerrainMesh"/>
  </OnRender>
  <OnClose>
    <ZExpression Comment="Destroy physical world" Expression="zbtDestroyWorld(World);"/>
  </OnClose>
  <Lights>
    <Light Position="20 50 20" Color="1 1 0 1" SpotDirection="0 -1 0" SpotCutoff="0"/>
  </Lights>
  <Content>
    <Mesh Name="TerrainMesh">
      <Producers>
        <MeshBox Name="Terrain_MeshBox" Scale="0.5 0.5 1" XCount="30" YCount="30" Grid2DOnly="255"/>
        <MeshExpression VertexColors="255">
          <Expression>
<![CDATA[//

byte gridSizeX = Terrain.SizeDim1 - 1;
byte gridSizeY = Terrain.SizeDim2 - 1;

float x = round((V.X + 0.5) * gridSizeX); // V.X = [-0.5, 0.5[ so x = [0, 10[ for gridSizeX = 10
float y = round((0.5 - V.Y) * gridSizeY); // V.Y = [-0.5, 0.5[ so y = ]10, 0] for gridSizeY = 10

//float h = rnd();
float h = noise3(v.X*2, v.Y*2, TerrainGenOffset) * 2.5 + 0.6;

int scale = TerrainScale - 1;

float halfWidth = gridSizeX * scale * 0.5;
float halfDepth = gridSizeY * scale * 0.5;

// V.Y and V.Y are switched to avoid RenderTransformGroup Rotate.X = -0.25
V.X = x * scale - halfWidth;
V.Y = h * TerrainScaleHeight;
V.Z = y * scale - halfDepth;

// Storage in Terrain array is switched to avoid RenderTransformGroup Rotate.Y = -0.25
Terrain[y, x] = h;

// Colors
c.R = h+0.5;
c.G = h/2;
c.B = 0;]]>
          </Expression>
        </MeshExpression>
      </Producers>
    </Mesh>
    <Model Name="SphereModel" Position="-33.7846 3.3394 11.3442" Category="1" RenderOrder="1">
      <Definitions>
        <Variable Name="Sphere" Type="9"/>
      </Definitions>
      <OnSpawn>
        <ZExpression Comment="Init">
          <Expression>
<![CDATA[// create rigid body
Sphere = zbtCreateRigidBodyXYZ(0.1, SphereShape, 0, 20, 0, 0, 0, 0);

// set physical properties
zbtSetDamping(Sphere, 0.1, 0.1);
//zbtSetActivationState(rbId, TRUE);
zbtSetSleepingThresholds(Sphere, 0, 0);
zbtSetLinearVelocity(Sphere, random(0,9), 0, random(0,9));
zbtSetAngularVelocity(Sphere, random(0,1), random(0,1), random(0,1));

// set color
SphereColor.Color.R = rnd() + 0.1;
SphereColor.Color.G = rnd() + 0.1;
SphereColor.Color.B = rnd() + 0.1;]]>
          </Expression>
        </ZExpression>
      </OnSpawn>
      <OnUpdate>
        <ZExpression Comment="Update position and rotation">
          <Expression>
<![CDATA[zbtGetPosRot(Sphere, CurrentModel.Position, CurrentModel.Rotation);

if (CurrentModel.Position.Y < -3) @RemoveModel(Model:CurrentModel);]]>
          </Expression>
        </ZExpression>
      </OnUpdate>
      <OnRender>
        <UseMaterial Material="ObjectMaterial"/>
        <RenderSetColor Name="SphereColor" Color="0.9404 0.2947 0.476 1"/>
        <RenderMesh Mesh="SphereMesh"/>
      </OnRender>
      <OnRemove>
        <ZExpression Comment="Delete rigid body and shape" Expression="zbtDeleteRigidBody(Sphere);"/>
      </OnRemove>
    </Model>
    <Mesh Name="SphereMesh">
      <Producers>
        <MeshBox Scale="1 0.5 1" XCount="18" YCount="12" Grid2DOnly="255"/>
        <MeshExpression AutoNormals="0">
          <Expression>
<![CDATA[//

        float E, A, CO, X, Y, Z;

        // Convert range to radians

        E = v.Y*PI; // Elevation
        A = v.X*PI; // Azimuth

        // Convert spherical coordinates into cartesian

        CO = cos(E);

        X = sin(A)*CO;
        Y = sin(E);
        Z = cos(A)*CO;

        // Assign coordinates

        v.X = X;
        v.Y = Y;
        v.Z = Z;

        n.X = X;
        n.Y = Y;
        n.Z = Z;]]>
          </Expression>
        </MeshExpression>
      </Producers>
    </Mesh>
    <Group Comment="Bitmaps and Materials">
      <Children>
        <Material Name="ObjectMaterial" WireframeWidth="0" SpecularColor="0 0 0 1" EmissionColor="0 0 0 1"/>
        <Bitmap Name="TerrainBitmap" Width="16" Height="16" Filter="2">
          <Producers>
            <BitmapExpression UseBlankSource="1">
              <Expression>
<![CDATA[Pixel.R = x > 0.9 || y > 0.9 ? 0 :1;
Pixel.G = Pixel.R;
Pixel.B = Pixel.R;]]>
              </Expression>
            </BitmapExpression>
          </Producers>
        </Bitmap>
        <Material Name="TerrainMaterial" Color="1 1 1 0.5" SpecularColor="0 0 0 1" EmissionColor="0 0 0 1" DrawBackFace="255">
          <Textures>
            <MaterialTexture Texture="TerrainBitmap" TextureScale="100 100 1" TextureWrapMode="1" TexCoords="1"/>
          </Textures>
        </Material>
        <Bitmap Name="SkyBitmap" Width="16" Height="128" Filter="2">
          <Producers>
            <BitmapExpression>
              <Expression>
<![CDATA[float t;

// Symmetric gradient: 0 at middle, 1 at top and bottom
t = abs(Y - 0.5) * 2;

// Top & Bottom color (25, 51, 255) -> normalized
float r1 = 0.1;
float g1 = 0.2;
float b1 = 1;

// Middle color (0, 227, 230) -> normalized
float r2 = 0;
float g2 = 0.89;
float b2 = 0.9;

// Linear interpolation
Pixel.R = r2 * (1.0 - t) + r1 * t;
Pixel.G = g2 * (1.0 - t) + g1 * t;
Pixel.B = b2 * (1.0 - t) + b1 * t;]]>
              </Expression>
            </BitmapExpression>
          </Producers>
        </Bitmap>
        <Material Name="SkyMaterial" WireframeWidth="0" Light="0" SpecularColor="0 0 0 1" EmissionColor="0 0 0 1" DrawBackFace="255">
          <Textures>
            <MaterialTexture Texture="SkyBitmap" TextureScale="1 1 0" TextureY="0.1" TexCoords="1" Origin="0 0 0"/>
          </Textures>
        </Material>
      </Children>
    </Group>
  </Content>
</ZApplication>

I initially set the array size to [1,1], but I had to change it to a larger value. Otherwise, ZGE enters a death loop if it happens to crash while the terrain mesh is selected.

Everything is now handled in the createTerrain function, where you can set the xcount, ycount, scale, and height scale of the terrain.
However, it crashes if xcount and ycount are different… I still don’t know why.
User avatar
Kjell
Posts: 1980
Joined: Sat Feb 23, 2008 11:15 pm

Re: I need help with ZGEBullet zbtCreateHeightfieldTerrainShape

Post by Kjell »

Hi Ats,
Ats wrote: Mon Dec 08, 2025 12:35 pmHowever, it still crashes if xcount and ycount are different… I still don’t know why.
Don't forget that you ended up doing swapping x & y in your TerrainMesh ( Terrain[y, x] = h ) :wink:

K
User avatar
Ats
Posts: 927
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: I need help with ZGEBullet zbtCreateHeightfieldTerrainShape

Post by Ats »

I checked that already :?

Create Terrain

Code: Select all

// Order is inverted in Terrain array to avoid visual Y rotate later on
Terrain.SizeDim1 = ycount + 2;
Terrain.SizeDim2 = xcount + 2;
Terrain Mesh

Code: Select all

// Storage in Terrain array is switched to avoid RenderTransformGroup Rotate.Y = -0.25
Terrain[y, x] = h;
But it's clearly that last line that breaks if xcount != ycount
User avatar
Kjell
Posts: 1980
Joined: Sat Feb 23, 2008 11:15 pm

Re: I need help with ZGEBullet zbtCreateHeightfieldTerrainShape

Post by Kjell »

Hi Ats,

You're mixing up some of the axes in your expressions. For example "float x = round((V.X + 0.5) * gridSizeX)" in MeshExpression uses V.X but also gridSizeX .. which is basically set using "ycount" in createTerrain().

K
User avatar
Ats
Posts: 927
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: I need help with ZGEBullet zbtCreateHeightfieldTerrainShape

Post by Ats »

I'm not sure. After trying things with those lines that weren't conclusive, I managed to make it work just by inverting the order of array size in the physical terrain generation:

xptr sh = zbtCreateHeightfieldTerrainShape(Terrain, Terrain.SizeDim2, Terrain.SizeDim1, -2, 2, ZBT_AXIS_Y_LINEAR, FALSE, FALSE);

Now this is working, but maybe I can optimize the variable names to make all those implicit rotations easier to read :lol:

Code: Select all

<?xml version="1.0" encoding="iso-8859-1" ?>
<ZApplication Name="App" Comment="ZgeBullet demo #2. Created by Rado1" Caption="Physics Demo 2" ClearColor="0 0 0 1" AmbientLightColor="0.6353 0.6353 0.6353 1" FrameRateStyle="1" ScreenMode="0" CameraPosition="-75.3461 30 26.888" CameraRotation="0.05 0.1954 0" LightPosition="0 0 0" ViewportRatio="3" CustomViewportRatio="1.6667" ClipFar="800" MouseVisible="255" FileVersion="2" AndroidPackageName="com.rado1.PhysicsDemo2">
  <OnLoaded>
    <ZExternalLibrary Comment="Bullet 3D physics" ModuleName="ZgeBullet_x64" CallingConvention="1" BeforeInitExp="if(ANDROID) this.ModuleName = &quot;./libZgeBullet.so&quot;;">
      <Source>
<![CDATA[/*
  ZgeBullet Library, a wrapper for the Bullet Physics Library.
  http://bulletphysics.org

  Project home
  https://github.com/Rado-1/ZgeBullet

  Download Windows DLL and Android shared library from
  https://github.com/Rado-1/ZgeBullet/releases

  Copyright (c) 2012-2015 Radovan Cervenka

  Version: 2.1 (2015-06-27)
*/


// Constants

// Triangle mesh types
const int ZBT_TRIANGLE_CONVEX_HULL_MESH = 1;
const int ZBT_TRIANGLE_CONCAVE_STATIC_MESH = 2;
const int ZBT_TRIANGLE_CONCAVE_DEFORMABLE_MESH = 3;

// Activation states
const int ZBT_ACTIVE_TAG = 1;
const int ZBT_ISLAND_SLEEPING = 2;
const int ZBT_WANTS_DEACTIVATION = 3;
const int ZBT_DISABLE_DEACTIVATION = 4;
const int ZBT_DISABLE_SIMULATION = 5;

// Default values of constraint limits
const float ZBT_DEFAULT_HINGE_SOFTNESS = 0.9;
const float ZBT_DEFAULT_HINGE_BIAS_FACTOR = 0.3;
const float ZBT_DEFAULT_HINGE_RELAXATION_FACTOR = 1.0;
const float ZBT_DEFAULT_CONE_TWIST_SOFTNESS = 1.0;
const float ZBT_DEFAULT_CONE_TWIST_BIAS_FACTOR = 0.3;
const float ZBT_DEFAULT_CONE_TWIST_RELAXATION_FACTOR = 1.0;

// Vehicle tunning defaults
const float ZBT_DEFAULT_VEHICLE_SUSP_STIFFNESS = 5.88;
const float ZBT_DEFAULT_VEHICLE_SUSP_COMPRESSION = 0.83;
const float ZBT_DEFAULT_VEHICLE_SUSP_DAMPING = 0.88;
const float ZBT_DEFAULT_VEHICLE_SUSP_MAX_SUSP_TRAVEL_CM = 500.0;
const float ZBT_DEFAULT_VEHICLE_SUSP_FORCE = 6000.0;
const float ZBT_DEFAULT_VEHICLE_FRICTION_SLIP = 10.5;

// Axes
const int ZBT_AXIS_X_LINEAR = 0;
const int ZBT_AXIS_Y_LINEAR = 1;
const int ZBT_AXIS_Z_LINEAR = 2;
const int ZBT_AXIS_X_ANGULAR = 3;
const int ZBT_AXIS_Y_ANGULAR = 4;
const int ZBT_AXIS_Z_ANGULAR = 5;

// Collision flags
const int ZBT_CF_STATIC_OBJECT= 1;
const int ZBT_CF_KINEMATIC_OBJECT= 2;
const int ZBT_CF_NO_CONTACT_RESPONSE = 4;
const int ZBT_CF_CUSTOM_MATERIAL_CALLBACK = 8;
const int ZBT_CF_CHARACTER_OBJECT = 16;
const int ZBT_CF_DISABLE_SPU_COLLISION_PROCESSING = 64;


// Functions


// World

xptr zbtCreateWorld() {}

void zbtDestroyWorld(xptr world) {}

void zbtSetCurrentWorld(xptr world) {}

void zbtSetWorldGravity(float x, float y, float z) {}

void zbtStepSimulation(float timeStep, int maxSubSteps, float fixedTimeStep) {}


// Collision shapes
xptr zbtCreateStaticPlaneShape(
	float normalX, float normalY, float normalZ, float planeConstant) {}

xptr zbtCreateBoxShape(float x, float y, float z) {}

xptr zbtCreateSphereShape(float radius) {}

xptr zbtCreateScalableSphereShape(float radius) {}

xptr zbtCreateConeShape(float radius, float height) {}

xptr zbtCreateCylinderShape(float radius, float height) {}

xptr zbtCreateCapsuleShape(float radius, float height) {}

xptr zbtCreateCompoundShape() {}

xptr zbtAddChildShape(xptr compoundShape, xptr childShape,
	float x, float y, float z, float rx, float ry, float rz) {}

xptr zbtRemoveChildShape(xptr compoundShape, xptr childShape) {}

xptr zbtCreateHeightfieldTerrainShape(xptr heightfieldData,
	int width, int length, float minHeight, float maxHeight, int upAxis,
	int bFlipQuadEdges, int bDiamondSubdivision) {}

xptr zbtCreateConvexHullShape(xptr points, int numPoints) {}

xptr zbtCreateMultiSphereShape(xptr positions, xptr radii, int numSpheres) {}

xptr zbtCreateTriangleMeshShape(xptr triangles, int numTriangles, int meshType) {}

void zbtUpdateDeformableTriangleMesh(xptr triangleMeshShape) {}

void zbtSetShapeLocalScaling(xptr shape, float x, float y, float z) {}

void zbtSetShapeMargin(xptr shape, float margin) {}

void zbtDeleteShape(xptr shape) {}

void zbtDeleteAllShapes() {}


// Rigid bodies

xptr zbtCreateRigidBodyXYZ(float mass, xptr shape,
	float x, float y, float z, float rx, float ry, float rz) {}

xptr zbtCreateRigidBody(float mass, xptr shape, xptr position, xptr rotation) {}

void zbtDeleteRigidBody(xptr rigidBody) {}

void zbtSetMass(xptr rigidBody, float mass) {}

void zbtSetDamping(xptr rigidBody, float linearDamping, float angularDamping) {}

void zbtSetLinearFactor(xptr rigidBody, float x, float y, float z) {}

void zbtSetAngularFactor(xptr rigidBody, float x, float y, float z) {}

void zbtSetGravity(xptr rigidBody, float x, float y, float z) {}

void zbtSetLinearVelocity(xptr rigidBody, float x, float y, float z) {}

void zbtGetLinearVelocity(xptr rigidBody,
	ref float outX, ref float outY, ref float outZ) {}

void zbtSetAngularVelocity(xptr rigidBody, float x, float y, float z) {}

void zbtGetAngularVelocity(xptr rigidBody,
	ref float outX, ref float outY, ref float outZ) {}

void zbtApplyCentralImpulse(xptr rigidBody, float x, float y, float z) {}

void zbtApplyTorqueImpulse(xptr rigidBody, float x, float y, float z) {}

void zbtApplyImpulse(xptr rigidBody, float x, float y, float z,
	float relX, float relY, float relZ) {}

void zbtSetSleepingThresholds(xptr rigidBody, float linear, float angular) {}


// Constraints and limits

int zbtAreConnected(xptr rigidBodyA, xptr rigidBodyB) {}

xptr zbtAddFixedConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz,
	float rotAx, float rotAy, float rotAz,
	float rotBx, float rotBy, float rotBz, int bDisableCollision) {}

xptr zbtAddPoint2PointConstraint1(xptr rigidBody,
	float pivotX, float pivotY, float pivotZ) {}

xptr zbtAddPoint2PointConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz, int bDisableCollision) {}

xptr zbtAddHingeConstraint1(xptr rigidBody,
	float pivotX, float pivotY, float pivotZ,
	float axisX, float axisY, float axisZ) {}

xptr zbtAddHingeConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz,
	float axisAx, float axisAy, float axisAz,
	float axisBx, float axisBy, float axisBz, int bDisableCollision) {}

void zbtSetHingeLimits(xptr hinge, float low, float high,
	float softness, float biasFactor, float relaxationFactor) {}

void zbtEnableHingeAngularMotor(xptr hinge, int bEnableMotor,
	float targetVelocity, float maxMotorImpulse) {}

xptr zbtAddConeTwistConstraint1(xptr rigidBody,
	float pivotX, float pivotY, float pivotZ,
	float rotX, float rotY, float rotZ) {}

xptr zbtAddConeTwistConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz,
	float rotAx, float rotAy, float rotAz,
	float rotBx, float rotBy, float rotBz, int bDisableCollision) {}

void zbtSetConeTwistLimits(xptr twist, float swingSpanA, float swingSpanB,
	float twistSpan, float damping, float softness, float biasFactor,
	float relaxationFactor) {}

void zbtEnableConeTwistMotor(xptr twist,
	int bEnableMotor, float maxMotorImpulse,
	float targetX, float targetY, float targetZ) {}

xptr zbtAddSliderConstraint1(xptr rigidBody,
	float pivotX, float pivotY, float pivotZ,
	float rotX, float rotY, float rotZ,
	int bUseLinearReferenceWorldFrame) {}

xptr zbtAddSliderConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz,
	float rotAx, float rotAy, float rotAz,
	float rotBx, float rotBy, float rotBz,
	int bUseLinearReferenceFrameA, int bDisableCollision) {}

void zbtSetSliderLimits(xptr slider,
	float linLower, float linUpper, float angLower, float angUpper) {}

void zbtSetSliderSoftness(xptr slider,
	float dirLin, float dirAng, float limLin, float limAng,
	float orthoLin, float orthoAng) {}

void zbtSetSliderRestitution(xptr slider,
	float dirLin, float dirAng, float limLin, float limAng,
	float orthoLin, float orthoAng) {}

void zbtSetSliderDamping(xptr slider,
	float dirLin, float dirAng, float limLin, float limAng,
	float orthoLin, float orthoAng) {}

void zbtEnableSliderLinearMotor(xptr slider, int bEnableMotor,
	float targetVelocity, float maxForce) {}

void zbtEnableSliderAngularMotor(xptr slider, int bEnableMotor,
	float targetVelocity, float maxForce) {}

xptr zbtAddGearConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float axisAx, float axisAy, float axisAz,
	float axisBx, float axisBy, float axisBz,
	float ratio) {}

void zbtSetGearConstraint(xptr gear,
	float axisAx, float axisAy, float axisAz,
	float axisBx, float axisBy, float axisBz,
	float ratio) {}

xptr zbtAddGeneric6DofConstraint1(xptr rigidBody,
	float pivotX, float pivotY, float pivotZ,
	float rotX, float rotY, float rotZ,
	int bUseLinearReferenceWorldFrame) {}

xptr zbtAddGeneric6DofConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz,
	float rotAx, float rotAy, float rotAz,
	float rotBx, float rotBy, float rotBz,
	int bUseLinearReferenceFrameA, int bDisableCollision) {}

void zbtSetGeneric6DofLimits(xptr dof, int axis, float lower, float upper) {}

void zbtSetGeneric6DofLinearLimits(xptr dof,
	float lowerX, float lowerY, float lowerZ,
	float upperX, float upperY, float upperZ) {}

void zbtSetGeneric6DofAngularLimits(xptr dof,
	float lowerX, float lowerY, float lowerZ,
	float upperX, float upperY, float upperZ) {}

xptr zbtAddGeneric6DofSpringConstraint1(xptr rigidBody,
	float pivotX, float pivotY, float pivotZ,
	float rotX, float rotY, float rotZ,
	int bUseLinearReferenceWorldFrame) {}

xptr zbtAddGeneric6DofSpringConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz,
	float rotAx, float rotAy, float rotAz,
	float rotBx, float rotBy, float rotBz,
	int bUseLinearReferenceFrameA, int bDisableCollision) {}

void zbtSetGeneric6DofSpring(xptr spring,
	int axis, int bEnableSpring, float stiffness, float damping,
	float equilibriumPoint) {}

void zbtSetEnabled(xptr constraint, int bEnabled) {}

void zbtDeleteConstraint(xptr constraint) {}


// Raycast vehicle

void zbtSetVehicleTunning(float suspStiffness, float suspCompression,
	float suspDamping, float maxSuspTravelCm, float maxSuspForce,
	float frictionSlip) {}

xptr zbtCreateRaycastVehicle(xptr carChassis,
	int rightAxis, int upAxis, int forwardAxis) {}

int zbtAddWheel(xptr vehicle,
	float connectionPointX, float connectionPointY, float connectionPointZ,
	float directionX, float directionY, float directionZ,
	float wheelAxleX, float wheelAxleY, float wheelAxleZ,
	float wheelRadius, float suspRestLength, int bIsFrontWheel) {}

void zbtSetWheelIsFront(xptr vehicle, int wheelId, int bIsFront) {}

void zbtSetWheelRadius(xptr vehicle, int wheelId, float radius) {}

void zbtSetWheelRollInfluence(xptr vehicle, int wheelId, float rollInfluence) {}

void zbtSetWheelFrictionSlip(xptr vehicle, int wheelId, float frictionSlip) {}

void zbtSetWheelSuspRestLength(xptr vehicle, int wheelId, float suspRestLength) {}

void zbtSetWheelMaxSuspTravel(xptr vehicle, int wheelId, float maxSuspTravel) {}

void zbtSetWheelSuspStiffness(xptr vehicle, int wheelId, float suspStiffness) {}

void zbtSetWheelDampingCompression(xptr vehicle, int wheelId,
	float dampingCompression) {}

void zbtSetWheelDampingRelaxation(xptr vehicle, int wheelId,
	float dampingRelaxation) {}

void zbtSetWheelSteering(xptr vehicle, int wheelId, float steering) {}

void zbtSetWheelEngineForce(xptr vehicle, int wheelId, float force) {}

void zbtSetWheelBrake(xptr vehicle, int wheelId, float brake) {}

void zbtResetVehicleSusp(xptr vehicle) {}

float zbtGetVehicleCurrentSpeed(xptr vehicle) {}

void zbtGetWheelPositionXYZ(xptr vehicle, int wheelId,
	ref float outX, ref float outY, ref float outZ) {}

void zbtGetWheelPosition(xptr vehicle, int wheelId, xptr outPosition) {}

void zbtGetWheelRotationXYZ(xptr vehicle, int wheelId,
	ref float outRx, ref float outRy, ref float outRz) {}

void zbtGetWheelRotation(xptr vehicle, int wheelId, xptr outRotation) {}

void zbtGetWheelPosRotXYZ(xptr vehicle, int wheelId,
	ref float outX, ref float outY, ref float outZ,
	ref float outRx, ref float outRy, ref float outRz) {}

void zbtGetWheelPosRot(xptr vehicle, int wheelId,
	xptr outPosition, xptr outRotation) {}

void zbtDeleteRaycastVehicle(xptr vehicle) {}


// Ghost object

xptr zbtCreateGhostObject(xptr shape,
	float x, float y, float z, float rx, float ry, float rz) {}

void zbtDeleteGhostObject(xptr ghostObject) {}

int zbtGetNumOverlappingObjects(xptr ghostObject) {}

xptr zbtGetOverlappingObject(xptr ghostObject, int index) {}


// Kinematic character controller

xptr zbtCreateKinematicCharacterController(
	xptr ghostObject, float stepHeight) {}

void zbtDeleteKinematicCharacterController(xptr controller) {}

void zbtSetCharacterUpAxis(xptr controller, int axis) {}

void zbtSetCharacterWalkDirection(xptr controller,
	float x, float y, float z) {}

void zbtSetCharacterVelocityForTimeInterval(xptr controller,
	float x, float y, float z, float timeInterval) {}

void zbtCharacterWarp(xptr controller, float x, float y, float z) {}

void zbtSetCharacterFallSpeed(xptr controller, float fallSpeed) {}

void zbtSetCharacterJumpSpeed(xptr controller, float jumpSpeed) {}

void zbtSetCharacterMaxJumpHeight(xptr controller, float maxJumpHeight) {}

int zbtCharacterCanJump(xptr controller) {}

void zbtCharacterJump(xptr controller) {}

void zbtSetCharacterGravity(xptr controller, float gravity) {}

void zbtSetCharacterMaxSlope(xptr controller, float slope) {}

void zbtSetCharacterUseGhostSweepTest(xptr controller,
	int bUseGhostObjectSweepTest) {}

int zbtCharacterOnGround(xptr controller) {}

void zbtCharacterReset(xptr controller) {}

void zbtSetCharacterUpInterpolate(xptr controller, int bInterpolate) {}


// Collision objects (in general)

void zbtSetFriction(xptr obj, float friction) {}

void zbtSetRestitution(xptr obj, float restitution) {}

void zbtSetHitFraction(xptr obj, float hitFraction) {}

void zbtGetPositionXYZ(xptr obj,
	ref float outX, ref float outY, ref float outZ) {}

void zbtGetPosition(xptr obj, xptr outPosition) {}

void zbtSetPositionXYZ(xptr obj, float x, float y, float z) {}

void zbtSetPosition(xptr obj, xptr position) {}

void zbtGetRotationXYZ(xptr obj,
	ref float outRx, ref float outRy, ref float outRz) {}

void zbtGetRotation(xptr obj, xptr outRotation) {}

void zbtSetRotationXYZ(xptr obj, float rx, float ry, float rz) {}

void zbtSetRotation(xptr obj, xptr rotation) {}

void zbtGetPosRotXYZ(xptr obj,
	ref float outX, ref float outY, ref float outZ,
	ref float outRx, ref float outRy, ref float outRz) {}

void zbtGetPosRot(xptr obj, xptr outPosition, xptr outRotation) {}

void zbtSetPosRotXYZ(xptr obj,
	float x, float y, float z,
	float rx, float ry, float rz) {}

void zbtSetPosRot(xptr obj, xptr position, xptr rotation) {}

void zbtSetCollisionFlags(xptr obj, int flags) {}

int zbtIsActive(xptr obj) {}

void zbtActivate(xptr obj, int bForceActivation) {}

void zbtSetActivationState(xptr obj, int newState) {}

void zbtForceActivationState(xptr obj, int newState) {}

void zbtSetDeactivationTime(xptr obj, float time) {}

void zbtSetUserIndex(xptr obj, int index) {}

int zbtGetUserIndex(xptr obj) {}

void zbtSetUserModel(xptr obj, model userModel) {}

model zbtGetUserModel(xptr obj) {}


// Collision detection

void zbtSetIgnoreCollisionCheck(xptr objA, xptr objB,
	int bIgnoreCollisionCheck) {}

int zbtStartCollisionDetection() {}

int zbtGetNextContact(xptr outObjA, xptr outObjB,
	xptr outPosA, xptr outPosB, xptr outNormal) {}

void zbtGetCollidedObjects(int contactIndex, xptr outObjA, xptr outObjB) {}

int zbtIsColliding(xptr obj) {}

int zbtGetNumberOfCollisions(xptr obj) {}

int zbtIsCollidedWith(xptr objA, xptr objB) {}


// Raycasting

xptr zbtRayTest(float fromX, float fromY, float fromZ, float toX, float toY, float toZ) {}

void zbtGetRayTestHitPointXYZ(ref float outX, ref float outY, ref float outZ) {}

void zbtGetRayTestHitPoint(xptr outPosition) {}

void zbtGetRayTestHitNormalXYZ(ref float outX, ref float outY, ref float outZ) {}

void zbtGetRayTestHitNormal(xptr outNormal) {}]]>
      </Source>
    </ZExternalLibrary>
    <ZLibrary Comment="Globals &amp; functions">
      <Source>
<![CDATA[// CONSTANTS

// boolean
const int FALSE = 0;
const int TRUE = 1;

// goniometric
const float PIx2 = PI * 2.0;
const float ROT90 = 0.25;

// VARIABLES

xptr World;
xptr SphereShape;


// Create Terrain

float[32, 32] Terrain;
byte TerrainScale, TerrainScaleHeight;
float TerrainGenOffset;

void createTerrain(byte xcount, byte ycount, byte scale, byte hscale)
{
  // Order is inverted in Terrain array to avoid visual Y rotate later on
  Terrain.SizeDim1 = ycount + 2;
  Terrain.SizeDim2 = xcount + 2;

  TerrainScale = scale;
  TerrainScaleHeight = hscale;

  // Generate Terrain Mesh
  Terrain_MeshBox.XCount = xcount;
  Terrain_MeshBox.YCount = ycount;
  @RefreshContent(Component: TerrainMesh);

  // Generate Terrain Physics
  xptr sh = zbtCreateHeightfieldTerrainShape(Terrain, Terrain.SizeDim2, Terrain.SizeDim1, -2, 2, ZBT_AXIS_Y_LINEAR, FALSE, FALSE);
  zbtSetShapeLocalScaling(sh, TerrainScale - 1, TerrainScaleHeight, TerrainScale - 1);
  xptr rb = zbtCreateRigidBodyXYZ(0, sh, 0, 0, 0, 0, 0, 0);
  zbtSetFriction(rb, 1);
}]]>
      </Source>
    </ZLibrary>
    <ZExpression Comment="Init">
      <Expression>
<![CDATA[// init random seed
setRandomSeed(getSystemTime());

// init physical world
World = zbtCreateWorld();
zbtSetCurrentWorld(World);
zbtSetWorldGravity(0, -10, 0);

// create sphere collision shape
SphereShape = zbtCreateSphereShape(1.0);

// create terrain: xcount, ycount, scale, height scale
createTerrain(50, 20, 4, 20);]]>
      </Expression>
    </ZExpression>
  </OnLoaded>
  <OnUpdate>
    <ZExpression Comment="Update simulation and rotate camera">
      <Expression>
<![CDATA[// simulation step
float t = App.DeltaTime;
zbtStepSimulation(t, 3, t/2);

// Update terrain geometry
TerrainGenOffset += App.DeltaTime / 4;
@RefreshContent(Component: TerrainMesh);

// rotate camera
t = App.Time / 30;
App.CameraPosition.X = cos(t * PIx2) * 80;
App.CameraPosition.Z = sin(t * PIx2) * 80;
App.CameraRotation.Y = t - ROT90;]]>
      </Expression>
    </ZExpression>
    <Timer Comment="Spawn spheres" Interval="0.5">
      <OnTimer>
        <SpawnModel Model="SphereModel"/>
      </OnTimer>
    </Timer>
    <KeyPress Comment="Space - remove spheres" Keys=" " RepeatDelay="0.5">
      <OnPressed>
        <RemoveAllModels OfType="SphereModel"/>
      </OnPressed>
    </KeyPress>
  </OnUpdate>
  <OnRender>
    <RenderTransformGroup Comment="Sky" Scale="150 100 150" Translate="0 15 0">
      <Children>
        <UseMaterial Material="SkyMaterial"/>
        <RenderMesh Mesh="SphereMesh"/>
      </Children>
    </RenderTransformGroup>
    <UseMaterial Material="TerrainMaterial"/>
    <RenderMesh Mesh="TerrainMesh"/>
  </OnRender>
  <OnClose>
    <ZExpression Comment="Destroy physical world" Expression="zbtDestroyWorld(World);"/>
  </OnClose>
  <Lights>
    <Light Position="20 50 20" Color="1 1 0 1" SpotDirection="0 -1 0" SpotCutoff="0"/>
  </Lights>
  <Content>
    <Mesh Name="TerrainMesh">
      <Producers>
        <MeshBox Name="Terrain_MeshBox" Scale="0.5 0.5 1" XCount="30" YCount="50" Grid2DOnly="255"/>
        <MeshExpression VertexColors="255">
          <Expression>
<![CDATA[//

byte gridSizeY = Terrain.SizeDim1 - 1;
byte gridSizeX = Terrain.SizeDim2 - 1;

float x = round((V.X + 0.5) * gridSizeX); // V.X = [-0.5, 0.5[ so x = [0, 10[ for gridSizeX = 10
float y = round((0.5 - V.Y) * gridSizeY); // V.Y = [-0.5, 0.5[ so y = ]10, 0] for gridSizeY = 10

//float h = rnd();
float h = noise3(v.X*2, v.Y*2, TerrainGenOffset) * 2.5 + 0.6;

int scale = TerrainScale - 1;

float halfWidth = gridSizeX * scale * 0.5;
float halfDepth = gridSizeY * scale * 0.5;

// V.Y and V.Y are switched to avoid RenderTransformGroup Rotate.X = -0.25
V.X = x * scale - halfWidth;
V.Y = h * TerrainScaleHeight;
V.Z = y * scale - halfDepth;

// Storage in Terrain array is switched to avoid RenderTransformGroup Rotate.Y = -0.25
Terrain[y, x] = h;

// Colors
c.R = h+0.5;
c.G = h/2;
c.B = 0;]]>
          </Expression>
        </MeshExpression>
      </Producers>
    </Mesh>
    <Model Name="SphereModel" Position="-33.7846 3.3394 11.3442" Category="1" RenderOrder="1">
      <Definitions>
        <Variable Name="Sphere" Type="9"/>
      </Definitions>
      <OnSpawn>
        <ZExpression Comment="Init">
          <Expression>
<![CDATA[// create rigid body
Sphere = zbtCreateRigidBodyXYZ(0.1, SphereShape, 0, 20, 0, 0, 0, 0);

// set physical properties
zbtSetDamping(Sphere, 0.1, 0.1);
//zbtSetActivationState(rbId, TRUE);
zbtSetSleepingThresholds(Sphere, 0, 0);
zbtSetLinearVelocity(Sphere, random(0,9), 0, random(0,9));
zbtSetAngularVelocity(Sphere, random(0,1), random(0,1), random(0,1));

// set color
SphereColor.Color.R = rnd() + 0.1;
SphereColor.Color.G = rnd() + 0.1;
SphereColor.Color.B = rnd() + 0.1;]]>
          </Expression>
        </ZExpression>
      </OnSpawn>
      <OnUpdate>
        <ZExpression Comment="Update position and rotation">
          <Expression>
<![CDATA[zbtGetPosRot(Sphere, CurrentModel.Position, CurrentModel.Rotation);

if (CurrentModel.Position.Y < -3) @RemoveModel(Model:CurrentModel);]]>
          </Expression>
        </ZExpression>
      </OnUpdate>
      <OnRender>
        <UseMaterial Material="ObjectMaterial"/>
        <RenderSetColor Name="SphereColor" Color="0.9404 0.2947 0.476 1"/>
        <RenderMesh Mesh="SphereMesh"/>
      </OnRender>
      <OnRemove>
        <ZExpression Comment="Delete rigid body and shape" Expression="zbtDeleteRigidBody(Sphere);"/>
      </OnRemove>
    </Model>
    <Mesh Name="SphereMesh">
      <Producers>
        <MeshBox Scale="1 0.5 1" XCount="18" YCount="12" Grid2DOnly="255"/>
        <MeshExpression AutoNormals="0">
          <Expression>
<![CDATA[//

        float E, A, CO, X, Y, Z;

        // Convert range to radians

        E = v.Y*PI; // Elevation
        A = v.X*PI; // Azimuth

        // Convert spherical coordinates into cartesian

        CO = cos(E);

        X = sin(A)*CO;
        Y = sin(E);
        Z = cos(A)*CO;

        // Assign coordinates

        v.X = X;
        v.Y = Y;
        v.Z = Z;

        n.X = X;
        n.Y = Y;
        n.Z = Z;]]>
          </Expression>
        </MeshExpression>
      </Producers>
    </Mesh>
    <Group Comment="Bitmaps and Materials">
      <Children>
        <Material Name="ObjectMaterial" WireframeWidth="0" SpecularColor="0 0 0 1" EmissionColor="0 0 0 1"/>
        <Bitmap Name="TerrainBitmap" Width="16" Height="16" Filter="2">
          <Producers>
            <BitmapExpression UseBlankSource="1">
              <Expression>
<![CDATA[Pixel.R = x > 0.9 || y > 0.9 ? 0 :1;
Pixel.G = Pixel.R;
Pixel.B = Pixel.R;]]>
              </Expression>
            </BitmapExpression>
          </Producers>
        </Bitmap>
        <Material Name="TerrainMaterial" Color="1 1 1 0.5" SpecularColor="0 0 0 1" EmissionColor="0 0 0 1" DrawBackFace="255">
          <Textures>
            <MaterialTexture Texture="TerrainBitmap" TextureScale="100 100 1" TextureWrapMode="1" TexCoords="1"/>
          </Textures>
        </Material>
        <Bitmap Name="SkyBitmap" Width="16" Height="128" Filter="2">
          <Producers>
            <BitmapExpression>
              <Expression>
<![CDATA[float t;

// Symmetric gradient: 0 at middle, 1 at top and bottom
t = abs(Y - 0.5) * 2;

// Top & Bottom color (25, 51, 255) -> normalized
float r1 = 0.1;
float g1 = 0.2;
float b1 = 1;

// Middle color (0, 227, 230) -> normalized
float r2 = 0;
float g2 = 0.89;
float b2 = 0.9;

// Linear interpolation
Pixel.R = r2 * (1.0 - t) + r1 * t;
Pixel.G = g2 * (1.0 - t) + g1 * t;
Pixel.B = b2 * (1.0 - t) + b1 * t;]]>
              </Expression>
            </BitmapExpression>
          </Producers>
        </Bitmap>
        <Material Name="SkyMaterial" WireframeWidth="0" Light="0" SpecularColor="0 0 0 1" EmissionColor="0 0 0 1" DrawBackFace="255">
          <Textures>
            <MaterialTexture Texture="SkyBitmap" TextureScale="1 1 0" TextureY="0.1" TexCoords="1" Origin="0 0 0"/>
          </Textures>
        </Material>
      </Children>
    </Group>
  </Content>
</ZApplication>
User avatar
Ats
Posts: 927
Joined: Fri Sep 28, 2012 10:05 am
Contact:

Re: I need help with ZGEBullet zbtCreateHeightfieldTerrainShape

Post by Ats »

I got rid of the TerrainScale - 1 (the old scale 9, 10, 9 when creating the physics).

Code: Select all

<?xml version="1.0" encoding="iso-8859-1" ?>
<ZApplication Name="App" Comment="ZgeBullet demo #2. Created by Rado1" Caption="Physics Demo 2" ClearColor="0 0 0 1" AmbientLightColor="0.6353 0.6353 0.6353 1" FrameRateStyle="1" ScreenMode="0" CameraPosition="-51.7061 30 61.0449" CameraRotation="0.05 5.1118 0" LightPosition="0 0 0" ViewportRatio="3" CustomViewportRatio="1.6667" ClipFar="800" MouseVisible="255" FileVersion="2" AndroidPackageName="com.rado1.PhysicsDemo2">
  <OnLoaded>
    <ZExternalLibrary Comment="Bullet 3D physics" ModuleName="ZgeBullet_x64" CallingConvention="1" BeforeInitExp="if(ANDROID) this.ModuleName = &quot;./libZgeBullet.so&quot;;">
      <Source>
<![CDATA[/*
  ZgeBullet Library, a wrapper for the Bullet Physics Library.
  http://bulletphysics.org

  Project home
  https://github.com/Rado-1/ZgeBullet

  Download Windows DLL and Android shared library from
  https://github.com/Rado-1/ZgeBullet/releases

  Copyright (c) 2012-2015 Radovan Cervenka

  Version: 2.1 (2015-06-27)
*/


// Constants

// Triangle mesh types
const int ZBT_TRIANGLE_CONVEX_HULL_MESH = 1;
const int ZBT_TRIANGLE_CONCAVE_STATIC_MESH = 2;
const int ZBT_TRIANGLE_CONCAVE_DEFORMABLE_MESH = 3;

// Activation states
const int ZBT_ACTIVE_TAG = 1;
const int ZBT_ISLAND_SLEEPING = 2;
const int ZBT_WANTS_DEACTIVATION = 3;
const int ZBT_DISABLE_DEACTIVATION = 4;
const int ZBT_DISABLE_SIMULATION = 5;

// Default values of constraint limits
const float ZBT_DEFAULT_HINGE_SOFTNESS = 0.9;
const float ZBT_DEFAULT_HINGE_BIAS_FACTOR = 0.3;
const float ZBT_DEFAULT_HINGE_RELAXATION_FACTOR = 1.0;
const float ZBT_DEFAULT_CONE_TWIST_SOFTNESS = 1.0;
const float ZBT_DEFAULT_CONE_TWIST_BIAS_FACTOR = 0.3;
const float ZBT_DEFAULT_CONE_TWIST_RELAXATION_FACTOR = 1.0;

// Vehicle tunning defaults
const float ZBT_DEFAULT_VEHICLE_SUSP_STIFFNESS = 5.88;
const float ZBT_DEFAULT_VEHICLE_SUSP_COMPRESSION = 0.83;
const float ZBT_DEFAULT_VEHICLE_SUSP_DAMPING = 0.88;
const float ZBT_DEFAULT_VEHICLE_SUSP_MAX_SUSP_TRAVEL_CM = 500.0;
const float ZBT_DEFAULT_VEHICLE_SUSP_FORCE = 6000.0;
const float ZBT_DEFAULT_VEHICLE_FRICTION_SLIP = 10.5;

// Axes
const int ZBT_AXIS_X_LINEAR = 0;
const int ZBT_AXIS_Y_LINEAR = 1;
const int ZBT_AXIS_Z_LINEAR = 2;
const int ZBT_AXIS_X_ANGULAR = 3;
const int ZBT_AXIS_Y_ANGULAR = 4;
const int ZBT_AXIS_Z_ANGULAR = 5;

// Collision flags
const int ZBT_CF_STATIC_OBJECT= 1;
const int ZBT_CF_KINEMATIC_OBJECT= 2;
const int ZBT_CF_NO_CONTACT_RESPONSE = 4;
const int ZBT_CF_CUSTOM_MATERIAL_CALLBACK = 8;
const int ZBT_CF_CHARACTER_OBJECT = 16;
const int ZBT_CF_DISABLE_SPU_COLLISION_PROCESSING = 64;


// Functions


// World

xptr zbtCreateWorld() {}

void zbtDestroyWorld(xptr world) {}

void zbtSetCurrentWorld(xptr world) {}

void zbtSetWorldGravity(float x, float y, float z) {}

void zbtStepSimulation(float timeStep, int maxSubSteps, float fixedTimeStep) {}


// Collision shapes
xptr zbtCreateStaticPlaneShape(
	float normalX, float normalY, float normalZ, float planeConstant) {}

xptr zbtCreateBoxShape(float x, float y, float z) {}

xptr zbtCreateSphereShape(float radius) {}

xptr zbtCreateScalableSphereShape(float radius) {}

xptr zbtCreateConeShape(float radius, float height) {}

xptr zbtCreateCylinderShape(float radius, float height) {}

xptr zbtCreateCapsuleShape(float radius, float height) {}

xptr zbtCreateCompoundShape() {}

xptr zbtAddChildShape(xptr compoundShape, xptr childShape,
	float x, float y, float z, float rx, float ry, float rz) {}

xptr zbtRemoveChildShape(xptr compoundShape, xptr childShape) {}

xptr zbtCreateHeightfieldTerrainShape(xptr heightfieldData,
	int width, int length, float minHeight, float maxHeight, int upAxis,
	int bFlipQuadEdges, int bDiamondSubdivision) {}

xptr zbtCreateConvexHullShape(xptr points, int numPoints) {}

xptr zbtCreateMultiSphereShape(xptr positions, xptr radii, int numSpheres) {}

xptr zbtCreateTriangleMeshShape(xptr triangles, int numTriangles, int meshType) {}

void zbtUpdateDeformableTriangleMesh(xptr triangleMeshShape) {}

void zbtSetShapeLocalScaling(xptr shape, float x, float y, float z) {}

void zbtSetShapeMargin(xptr shape, float margin) {}

void zbtDeleteShape(xptr shape) {}

void zbtDeleteAllShapes() {}


// Rigid bodies

xptr zbtCreateRigidBodyXYZ(float mass, xptr shape,
	float x, float y, float z, float rx, float ry, float rz) {}

xptr zbtCreateRigidBody(float mass, xptr shape, xptr position, xptr rotation) {}

void zbtDeleteRigidBody(xptr rigidBody) {}

void zbtSetMass(xptr rigidBody, float mass) {}

void zbtSetDamping(xptr rigidBody, float linearDamping, float angularDamping) {}

void zbtSetLinearFactor(xptr rigidBody, float x, float y, float z) {}

void zbtSetAngularFactor(xptr rigidBody, float x, float y, float z) {}

void zbtSetGravity(xptr rigidBody, float x, float y, float z) {}

void zbtSetLinearVelocity(xptr rigidBody, float x, float y, float z) {}

void zbtGetLinearVelocity(xptr rigidBody,
	ref float outX, ref float outY, ref float outZ) {}

void zbtSetAngularVelocity(xptr rigidBody, float x, float y, float z) {}

void zbtGetAngularVelocity(xptr rigidBody,
	ref float outX, ref float outY, ref float outZ) {}

void zbtApplyCentralImpulse(xptr rigidBody, float x, float y, float z) {}

void zbtApplyTorqueImpulse(xptr rigidBody, float x, float y, float z) {}

void zbtApplyImpulse(xptr rigidBody, float x, float y, float z,
	float relX, float relY, float relZ) {}

void zbtSetSleepingThresholds(xptr rigidBody, float linear, float angular) {}


// Constraints and limits

int zbtAreConnected(xptr rigidBodyA, xptr rigidBodyB) {}

xptr zbtAddFixedConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz,
	float rotAx, float rotAy, float rotAz,
	float rotBx, float rotBy, float rotBz, int bDisableCollision) {}

xptr zbtAddPoint2PointConstraint1(xptr rigidBody,
	float pivotX, float pivotY, float pivotZ) {}

xptr zbtAddPoint2PointConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz, int bDisableCollision) {}

xptr zbtAddHingeConstraint1(xptr rigidBody,
	float pivotX, float pivotY, float pivotZ,
	float axisX, float axisY, float axisZ) {}

xptr zbtAddHingeConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz,
	float axisAx, float axisAy, float axisAz,
	float axisBx, float axisBy, float axisBz, int bDisableCollision) {}

void zbtSetHingeLimits(xptr hinge, float low, float high,
	float softness, float biasFactor, float relaxationFactor) {}

void zbtEnableHingeAngularMotor(xptr hinge, int bEnableMotor,
	float targetVelocity, float maxMotorImpulse) {}

xptr zbtAddConeTwistConstraint1(xptr rigidBody,
	float pivotX, float pivotY, float pivotZ,
	float rotX, float rotY, float rotZ) {}

xptr zbtAddConeTwistConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz,
	float rotAx, float rotAy, float rotAz,
	float rotBx, float rotBy, float rotBz, int bDisableCollision) {}

void zbtSetConeTwistLimits(xptr twist, float swingSpanA, float swingSpanB,
	float twistSpan, float damping, float softness, float biasFactor,
	float relaxationFactor) {}

void zbtEnableConeTwistMotor(xptr twist,
	int bEnableMotor, float maxMotorImpulse,
	float targetX, float targetY, float targetZ) {}

xptr zbtAddSliderConstraint1(xptr rigidBody,
	float pivotX, float pivotY, float pivotZ,
	float rotX, float rotY, float rotZ,
	int bUseLinearReferenceWorldFrame) {}

xptr zbtAddSliderConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz,
	float rotAx, float rotAy, float rotAz,
	float rotBx, float rotBy, float rotBz,
	int bUseLinearReferenceFrameA, int bDisableCollision) {}

void zbtSetSliderLimits(xptr slider,
	float linLower, float linUpper, float angLower, float angUpper) {}

void zbtSetSliderSoftness(xptr slider,
	float dirLin, float dirAng, float limLin, float limAng,
	float orthoLin, float orthoAng) {}

void zbtSetSliderRestitution(xptr slider,
	float dirLin, float dirAng, float limLin, float limAng,
	float orthoLin, float orthoAng) {}

void zbtSetSliderDamping(xptr slider,
	float dirLin, float dirAng, float limLin, float limAng,
	float orthoLin, float orthoAng) {}

void zbtEnableSliderLinearMotor(xptr slider, int bEnableMotor,
	float targetVelocity, float maxForce) {}

void zbtEnableSliderAngularMotor(xptr slider, int bEnableMotor,
	float targetVelocity, float maxForce) {}

xptr zbtAddGearConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float axisAx, float axisAy, float axisAz,
	float axisBx, float axisBy, float axisBz,
	float ratio) {}

void zbtSetGearConstraint(xptr gear,
	float axisAx, float axisAy, float axisAz,
	float axisBx, float axisBy, float axisBz,
	float ratio) {}

xptr zbtAddGeneric6DofConstraint1(xptr rigidBody,
	float pivotX, float pivotY, float pivotZ,
	float rotX, float rotY, float rotZ,
	int bUseLinearReferenceWorldFrame) {}

xptr zbtAddGeneric6DofConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz,
	float rotAx, float rotAy, float rotAz,
	float rotBx, float rotBy, float rotBz,
	int bUseLinearReferenceFrameA, int bDisableCollision) {}

void zbtSetGeneric6DofLimits(xptr dof, int axis, float lower, float upper) {}

void zbtSetGeneric6DofLinearLimits(xptr dof,
	float lowerX, float lowerY, float lowerZ,
	float upperX, float upperY, float upperZ) {}

void zbtSetGeneric6DofAngularLimits(xptr dof,
	float lowerX, float lowerY, float lowerZ,
	float upperX, float upperY, float upperZ) {}

xptr zbtAddGeneric6DofSpringConstraint1(xptr rigidBody,
	float pivotX, float pivotY, float pivotZ,
	float rotX, float rotY, float rotZ,
	int bUseLinearReferenceWorldFrame) {}

xptr zbtAddGeneric6DofSpringConstraint(xptr rigidBodyA, xptr rigidBodyB,
	float pivotAx, float pivotAy, float pivotAz,
	float pivotBx, float pivotBy, float pivotBz,
	float rotAx, float rotAy, float rotAz,
	float rotBx, float rotBy, float rotBz,
	int bUseLinearReferenceFrameA, int bDisableCollision) {}

void zbtSetGeneric6DofSpring(xptr spring,
	int axis, int bEnableSpring, float stiffness, float damping,
	float equilibriumPoint) {}

void zbtSetEnabled(xptr constraint, int bEnabled) {}

void zbtDeleteConstraint(xptr constraint) {}


// Raycast vehicle

void zbtSetVehicleTunning(float suspStiffness, float suspCompression,
	float suspDamping, float maxSuspTravelCm, float maxSuspForce,
	float frictionSlip) {}

xptr zbtCreateRaycastVehicle(xptr carChassis,
	int rightAxis, int upAxis, int forwardAxis) {}

int zbtAddWheel(xptr vehicle,
	float connectionPointX, float connectionPointY, float connectionPointZ,
	float directionX, float directionY, float directionZ,
	float wheelAxleX, float wheelAxleY, float wheelAxleZ,
	float wheelRadius, float suspRestLength, int bIsFrontWheel) {}

void zbtSetWheelIsFront(xptr vehicle, int wheelId, int bIsFront) {}

void zbtSetWheelRadius(xptr vehicle, int wheelId, float radius) {}

void zbtSetWheelRollInfluence(xptr vehicle, int wheelId, float rollInfluence) {}

void zbtSetWheelFrictionSlip(xptr vehicle, int wheelId, float frictionSlip) {}

void zbtSetWheelSuspRestLength(xptr vehicle, int wheelId, float suspRestLength) {}

void zbtSetWheelMaxSuspTravel(xptr vehicle, int wheelId, float maxSuspTravel) {}

void zbtSetWheelSuspStiffness(xptr vehicle, int wheelId, float suspStiffness) {}

void zbtSetWheelDampingCompression(xptr vehicle, int wheelId,
	float dampingCompression) {}

void zbtSetWheelDampingRelaxation(xptr vehicle, int wheelId,
	float dampingRelaxation) {}

void zbtSetWheelSteering(xptr vehicle, int wheelId, float steering) {}

void zbtSetWheelEngineForce(xptr vehicle, int wheelId, float force) {}

void zbtSetWheelBrake(xptr vehicle, int wheelId, float brake) {}

void zbtResetVehicleSusp(xptr vehicle) {}

float zbtGetVehicleCurrentSpeed(xptr vehicle) {}

void zbtGetWheelPositionXYZ(xptr vehicle, int wheelId,
	ref float outX, ref float outY, ref float outZ) {}

void zbtGetWheelPosition(xptr vehicle, int wheelId, xptr outPosition) {}

void zbtGetWheelRotationXYZ(xptr vehicle, int wheelId,
	ref float outRx, ref float outRy, ref float outRz) {}

void zbtGetWheelRotation(xptr vehicle, int wheelId, xptr outRotation) {}

void zbtGetWheelPosRotXYZ(xptr vehicle, int wheelId,
	ref float outX, ref float outY, ref float outZ,
	ref float outRx, ref float outRy, ref float outRz) {}

void zbtGetWheelPosRot(xptr vehicle, int wheelId,
	xptr outPosition, xptr outRotation) {}

void zbtDeleteRaycastVehicle(xptr vehicle) {}


// Ghost object

xptr zbtCreateGhostObject(xptr shape,
	float x, float y, float z, float rx, float ry, float rz) {}

void zbtDeleteGhostObject(xptr ghostObject) {}

int zbtGetNumOverlappingObjects(xptr ghostObject) {}

xptr zbtGetOverlappingObject(xptr ghostObject, int index) {}


// Kinematic character controller

xptr zbtCreateKinematicCharacterController(
	xptr ghostObject, float stepHeight) {}

void zbtDeleteKinematicCharacterController(xptr controller) {}

void zbtSetCharacterUpAxis(xptr controller, int axis) {}

void zbtSetCharacterWalkDirection(xptr controller,
	float x, float y, float z) {}

void zbtSetCharacterVelocityForTimeInterval(xptr controller,
	float x, float y, float z, float timeInterval) {}

void zbtCharacterWarp(xptr controller, float x, float y, float z) {}

void zbtSetCharacterFallSpeed(xptr controller, float fallSpeed) {}

void zbtSetCharacterJumpSpeed(xptr controller, float jumpSpeed) {}

void zbtSetCharacterMaxJumpHeight(xptr controller, float maxJumpHeight) {}

int zbtCharacterCanJump(xptr controller) {}

void zbtCharacterJump(xptr controller) {}

void zbtSetCharacterGravity(xptr controller, float gravity) {}

void zbtSetCharacterMaxSlope(xptr controller, float slope) {}

void zbtSetCharacterUseGhostSweepTest(xptr controller,
	int bUseGhostObjectSweepTest) {}

int zbtCharacterOnGround(xptr controller) {}

void zbtCharacterReset(xptr controller) {}

void zbtSetCharacterUpInterpolate(xptr controller, int bInterpolate) {}


// Collision objects (in general)

void zbtSetFriction(xptr obj, float friction) {}

void zbtSetRestitution(xptr obj, float restitution) {}

void zbtSetHitFraction(xptr obj, float hitFraction) {}

void zbtGetPositionXYZ(xptr obj,
	ref float outX, ref float outY, ref float outZ) {}

void zbtGetPosition(xptr obj, xptr outPosition) {}

void zbtSetPositionXYZ(xptr obj, float x, float y, float z) {}

void zbtSetPosition(xptr obj, xptr position) {}

void zbtGetRotationXYZ(xptr obj,
	ref float outRx, ref float outRy, ref float outRz) {}

void zbtGetRotation(xptr obj, xptr outRotation) {}

void zbtSetRotationXYZ(xptr obj, float rx, float ry, float rz) {}

void zbtSetRotation(xptr obj, xptr rotation) {}

void zbtGetPosRotXYZ(xptr obj,
	ref float outX, ref float outY, ref float outZ,
	ref float outRx, ref float outRy, ref float outRz) {}

void zbtGetPosRot(xptr obj, xptr outPosition, xptr outRotation) {}

void zbtSetPosRotXYZ(xptr obj,
	float x, float y, float z,
	float rx, float ry, float rz) {}

void zbtSetPosRot(xptr obj, xptr position, xptr rotation) {}

void zbtSetCollisionFlags(xptr obj, int flags) {}

int zbtIsActive(xptr obj) {}

void zbtActivate(xptr obj, int bForceActivation) {}

void zbtSetActivationState(xptr obj, int newState) {}

void zbtForceActivationState(xptr obj, int newState) {}

void zbtSetDeactivationTime(xptr obj, float time) {}

void zbtSetUserIndex(xptr obj, int index) {}

int zbtGetUserIndex(xptr obj) {}

void zbtSetUserModel(xptr obj, model userModel) {}

model zbtGetUserModel(xptr obj) {}


// Collision detection

void zbtSetIgnoreCollisionCheck(xptr objA, xptr objB,
	int bIgnoreCollisionCheck) {}

int zbtStartCollisionDetection() {}

int zbtGetNextContact(xptr outObjA, xptr outObjB,
	xptr outPosA, xptr outPosB, xptr outNormal) {}

void zbtGetCollidedObjects(int contactIndex, xptr outObjA, xptr outObjB) {}

int zbtIsColliding(xptr obj) {}

int zbtGetNumberOfCollisions(xptr obj) {}

int zbtIsCollidedWith(xptr objA, xptr objB) {}


// Raycasting

xptr zbtRayTest(float fromX, float fromY, float fromZ, float toX, float toY, float toZ) {}

void zbtGetRayTestHitPointXYZ(ref float outX, ref float outY, ref float outZ) {}

void zbtGetRayTestHitPoint(xptr outPosition) {}

void zbtGetRayTestHitNormalXYZ(ref float outX, ref float outY, ref float outZ) {}

void zbtGetRayTestHitNormal(xptr outNormal) {}]]>
      </Source>
    </ZExternalLibrary>
    <ZLibrary Comment="Globals &amp; functions">
      <Source>
<![CDATA[// CONSTANTS

// boolean
const int FALSE = 0;
const int TRUE = 1;

// goniometric
const float PIx2 = PI * 2.0;
const float ROT90 = 0.25;

// VARIABLES

xptr World;
xptr SphereShape;


// Create Terrain

float[32, 32] Terrain;
byte TerrainScale, TerrainScaleHeight;
float TerrainGenOffset;

void createTerrain(byte xcount, byte ycount, byte scale, byte hscale)
{
  // Order is inverted in Terrain array to avoid visual Y rotate later on
  Terrain.SizeDim1 = ycount + 2;
  Terrain.SizeDim2 = xcount + 2;

  TerrainScale = scale;
  TerrainScaleHeight = hscale;

  // Generate Terrain Mesh
  Terrain_MeshBox.XCount = xcount;
  Terrain_MeshBox.YCount = ycount;
  @RefreshContent(Component: TerrainMesh);

  // Generate Terrain Physics
  xptr sh = zbtCreateHeightfieldTerrainShape(Terrain, Terrain.SizeDim2, Terrain.SizeDim1, -2, 2, ZBT_AXIS_Y_LINEAR, FALSE, FALSE);
  zbtSetShapeLocalScaling(sh, TerrainScale, TerrainScaleHeight, TerrainScale);
  xptr rb = zbtCreateRigidBodyXYZ(0, sh, 0, 0, 0, 0, 0, 0);
  zbtSetFriction(rb, 1);
}]]>
      </Source>
    </ZLibrary>
    <ZExpression Comment="Init">
      <Expression>
<![CDATA[// init random seed
setRandomSeed(getSystemTime());

// init physical world
World = zbtCreateWorld();
zbtSetCurrentWorld(World);
zbtSetWorldGravity(0, -10, 0);

// create sphere collision shape
SphereShape = zbtCreateSphereShape(1.0);

// create terrain: xcount, ycount, scale, height scale
createTerrain(32, 32, 4, 10);]]>
      </Expression>
    </ZExpression>
  </OnLoaded>
  <OnUpdate>
    <ZExpression Comment="Update simulation and rotate camera">
      <Expression>
<![CDATA[// simulation step
float t = App.DeltaTime;
zbtStepSimulation(t, 3, t/2);

// Update terrain geometry
TerrainGenOffset += App.DeltaTime / 4;
@RefreshContent(Component: TerrainMesh);

// rotate camera
t = App.Time / 30;
App.CameraPosition.X = cos(t * PIx2) * 80;
App.CameraPosition.Z = sin(t * PIx2) * 80;
App.CameraRotation.Y = t - ROT90;]]>
      </Expression>
    </ZExpression>
    <Timer Comment="Spawn spheres" Interval="0.5">
      <OnTimer>
        <SpawnModel Model="SphereModel"/>
      </OnTimer>
    </Timer>
    <KeyPress Comment="Space - remove spheres" Keys=" " RepeatDelay="0.5">
      <OnPressed>
        <RemoveAllModels OfType="SphereModel"/>
      </OnPressed>
    </KeyPress>
  </OnUpdate>
  <OnRender>
    <RenderTransformGroup Comment="Sky" Scale="150 100 150" Translate="0 15 0">
      <Children>
        <UseMaterial Material="SkyMaterial"/>
        <RenderMesh Mesh="SphereMesh"/>
      </Children>
    </RenderTransformGroup>
    <UseMaterial Material="TerrainMaterial"/>
    <RenderMesh Mesh="TerrainMesh"/>
  </OnRender>
  <OnClose>
    <ZExpression Comment="Destroy physical world" Expression="zbtDestroyWorld(World);"/>
  </OnClose>
  <Lights>
    <Light Position="20 50 20" Color="1 1 0 1" SpotDirection="0 -1 0" SpotCutoff="0"/>
  </Lights>
  <Content>
    <Mesh Name="TerrainMesh">
      <Producers>
        <MeshBox Name="Terrain_MeshBox" Scale="0.5 0.5 1" XCount="32" YCount="32" Grid2DOnly="255"/>
        <MeshExpression VertexColors="255">
          <Expression>
<![CDATA[//

byte gridSizeY = Terrain.SizeDim1 - 1;
byte gridSizeX = Terrain.SizeDim2 - 1;

float x = round((V.X + 0.5) * gridSizeX); // V.X = [-0.5, 0.5[ so x = [0, 10[ for gridSizeX = 10
float y = round((0.5 - V.Y) * gridSizeY); // V.Y = [-0.5, 0.5[ so y = ]10, 0] for gridSizeY = 10

//float h = rnd();
float h = noise3(v.X*2, v.Y*2, TerrainGenOffset) * 2.5 + 0.6;

// Scale
float sx = gridSizeX * TerrainScale * 0.5;
float sy = gridSizeY * TerrainScale * 0.5;

// V.Y and V.Y are switched to avoid RenderTransformGroup Rotate.X = -0.25
V.X = x * TerrainScale - sx;
V.Z = y * TerrainScale - sy;
V.Y = h * TerrainScaleHeight;

// Storage in Terrain array is switched to avoid RenderTransformGroup Rotate.Y = -0.25
Terrain[y, x] = h;

// Colors
c.R = h+0.5;
c.G = h/2;
c.B = 0;]]>
          </Expression>
        </MeshExpression>
      </Producers>
    </Mesh>
    <Model Name="SphereModel" Position="-33.7846 3.3394 11.3442" Category="1" RenderOrder="1">
      <Definitions>
        <Variable Name="Sphere" Type="9"/>
      </Definitions>
      <OnSpawn>
        <ZExpression Comment="Init">
          <Expression>
<![CDATA[// create rigid body
Sphere = zbtCreateRigidBodyXYZ(0.1, SphereShape, 0, 20, 0, 0, 0, 0);

// set physical properties
zbtSetDamping(Sphere, 0.1, 0.1);
//zbtSetActivationState(rbId, TRUE);
zbtSetSleepingThresholds(Sphere, 0, 0);
zbtSetLinearVelocity(Sphere, random(0,9), 0, random(0,9));
zbtSetAngularVelocity(Sphere, random(0,1), random(0,1), random(0,1));

// set color
SphereColor.Color.R = rnd() + 0.1;
SphereColor.Color.G = rnd() + 0.1;
SphereColor.Color.B = rnd() + 0.1;]]>
          </Expression>
        </ZExpression>
      </OnSpawn>
      <OnUpdate>
        <ZExpression Comment="Update position and rotation">
          <Expression>
<![CDATA[zbtGetPosRot(Sphere, CurrentModel.Position, CurrentModel.Rotation);

if (CurrentModel.Position.Y < -3) @RemoveModel(Model:CurrentModel);]]>
          </Expression>
        </ZExpression>
      </OnUpdate>
      <OnRender>
        <UseMaterial Material="ObjectMaterial"/>
        <RenderSetColor Name="SphereColor" Color="0.9404 0.2947 0.476 1"/>
        <RenderMesh Mesh="SphereMesh"/>
      </OnRender>
      <OnRemove>
        <ZExpression Comment="Delete rigid body and shape" Expression="zbtDeleteRigidBody(Sphere);"/>
      </OnRemove>
    </Model>
    <Mesh Name="SphereMesh">
      <Producers>
        <MeshBox Scale="1 0.5 1" XCount="18" YCount="12" Grid2DOnly="255"/>
        <MeshExpression AutoNormals="0">
          <Expression>
<![CDATA[//

        float E, A, CO, X, Y, Z;

        // Convert range to radians

        E = v.Y*PI; // Elevation
        A = v.X*PI; // Azimuth

        // Convert spherical coordinates into cartesian

        CO = cos(E);

        X = sin(A)*CO;
        Y = sin(E);
        Z = cos(A)*CO;

        // Assign coordinates

        v.X = X;
        v.Y = Y;
        v.Z = Z;

        n.X = X;
        n.Y = Y;
        n.Z = Z;]]>
          </Expression>
        </MeshExpression>
      </Producers>
    </Mesh>
    <Group Comment="Bitmaps and Materials">
      <Children>
        <Material Name="ObjectMaterial" WireframeWidth="0" SpecularColor="0 0 0 1" EmissionColor="0 0 0 1"/>
        <Bitmap Name="TerrainBitmap" Width="16" Height="16" Filter="2">
          <Producers>
            <BitmapExpression UseBlankSource="1">
              <Expression>
<![CDATA[Pixel.R = x > 0.9 || y > 0.9 ? 0 :1;
Pixel.G = Pixel.R;
Pixel.B = Pixel.R;]]>
              </Expression>
            </BitmapExpression>
          </Producers>
        </Bitmap>
        <Material Name="TerrainMaterial" Color="1 1 1 0.5" SpecularColor="0 0 0 1" EmissionColor="0 0 0 1" DrawBackFace="255">
          <Textures>
            <MaterialTexture Texture="TerrainBitmap" TextureScale="100 100 1" TextureWrapMode="1" TexCoords="1"/>
          </Textures>
        </Material>
        <Bitmap Name="SkyBitmap" Width="16" Height="128" Filter="2">
          <Producers>
            <BitmapExpression>
              <Expression>
<![CDATA[float t;

// Symmetric gradient: 0 at middle, 1 at top and bottom
t = abs(Y - 0.5) * 2;

// Top & Bottom color (25, 51, 255) -> normalized
float r1 = 0.1;
float g1 = 0.2;
float b1 = 1;

// Middle color (0, 227, 230) -> normalized
float r2 = 0;
float g2 = 0.89;
float b2 = 0.9;

// Linear interpolation
Pixel.R = r2 * (1.0 - t) + r1 * t;
Pixel.G = g2 * (1.0 - t) + g1 * t;
Pixel.B = b2 * (1.0 - t) + b1 * t;]]>
              </Expression>
            </BitmapExpression>
          </Producers>
        </Bitmap>
        <Material Name="SkyMaterial" WireframeWidth="0" Light="0" SpecularColor="0 0 0 1" EmissionColor="0 0 0 1" DrawBackFace="255">
          <Textures>
            <MaterialTexture Texture="SkyBitmap" TextureScale="1 1 0" TextureY="0.1" TexCoords="1" Origin="0 0 0"/>
          </Textures>
        </Material>
      </Children>
    </Group>
  </Content>
</ZApplication>

I think I’m going to make a sub–sub-project for a little boat game, before going back to the sub-project that mixes pinball and surf... And then finally returning to activating collisions with the generated mountains in Omeganaut :lol:
Post Reply