// rotate by -90 degrees around X axis
Scene.Rotation := Vector4(1, 0, 0, -Deg(90));
There are various conventions for
which vector is "up" in 3D world
and which vector corresponds to the "direction" the creatures / player are facing.
By default, our engine follows the convention that "up" is in +Y axis.
This is consistent with glTF, X3D and other 3D formats.
Exporters from 3D authoring software are ready for this — e.g. Blender glTF, X3D exporters by default rotate models to change +Z axis (traditional "up" vector in Blender) to the +Y axis.
It is also consistent with 2D. E.g. "jump up" means you move in the +Y direction, in both 2D and 3D.
So things just work.
If you have existing models oriented such that +Z is "up", but you would like to use the engine default convention that +Y is "up", you can simply rotate them. You can rotate things in Castle Game Engine using the TCastleTransform.Rotation property. Note that TCastleScene also descends from TCastleTransform, so you can directly rotate a scene.
To rotate each single model from +Z to +Y, just set rotation for every TCastleScene:
// rotate by -90 degrees around X axis
Scene.Rotation := Vector4(1, 0, 0, -Deg(90));
Here’s a complete source code:
uses CastleWindow, CastleSceneCore, CastleScene, CastleVectors, CastleFilesUtils,
CastleViewport, CastleCameras, CastleUtils;
var
Window: TCastleWindow;
Viewport: TCastleViewport;
Scene: TCastleScene;
begin
Window := TCastleWindow.Create(Application);
Window.Open;
Viewport := TCastleViewport.Create(Application);
Viewport.FullSize := true;
Viewport.Camera.Translation := Vector3(0, 0, 6);
Window.Controls.InsertFront(Viewport);
Viewport.InsertFront(TCastleExamineNavigation.Create(Application));
Scene := TCastleScene.Create(Application);
Scene.Load('castle-data:/monkey_z_up.x3d');
Scene.PreciseCollisions := true;
// rotate by -90 degrees around X axis
Scene.Rotation := Vector4(1, 0, 0, -Deg(90));
Viewport.Items.Add(Scene);
Application.Run;
end.
The above option is best if you prefer to think "+Y direction is up" as soon as possible.
Alternatively, you could rotate a whole group of models (with their local transformations) from +Z to +Y, by using TCastleTransform as a group:
uses CastleWindow, CastleSceneCore, CastleScene, CastleVectors, CastleFilesUtils,
CastleViewport, CastleTransform, CastleCameras, CastleUtils;
var
Window: TCastleWindow;
Viewport: TCastleViewport;
Scene1, Scene2: TCastleScene;
Transform: TCastleTransform;
begin
Window := TCastleWindow.Create(Application);
Window.Open;
Viewport := TCastleViewport.Create(Application);
Viewport.FullSize := true;
Viewport.Camera.Translation := Vector3(0, 0, 6);
Window.Controls.InsertFront(Viewport);
Viewport.InsertFront(TCastleExamineNavigation.Create(Application));
Transform := TCastleTransform.Create(Application);
// rotate by 90 degrees around X axis
Transform.Rotation := Vector4(1, 0, 0, -Deg(90));
Scene1 := TCastleScene.Create(Application);
Scene1.Load('castle-data:/monkey_z_up.x3d');
Scene1.PreciseCollisions := true;
Scene1.Translation := Vector3(1, 1, 0);
Scene2 := TCastleScene.Create(Application);
Scene2.Load('castle-data:/monkey_z_up.x3d');
Scene2.PreciseCollisions := true;
Scene2.Translation := Vector3(-1, -1, 0);
Transform.Add(Scene1);
Transform.Add(Scene2);
Viewport.Items.Add(Transform);
Application.Run;
end.
Note that you can also rotate things in Castle Game Engine using TTransformNode.Rotation. But in this case, TCastleTransform.Rotation is simpler to use.
If you want to follow "+Y axis is up" convention (easier, i.e. you don’t really need to do anything):
When exporting from Blender (levels, creatures etc.), let it rotate the model, i.e. change +Z to +Y. This is the default behavior of the glTF and X3D exporters.
Optional: This step only matters if you use deprecated TCastleRootTransform.MainScene and TCastleViewport.AutoCamera and you set the initial camera by information in the file (like TViewpointNode in X3D or equivalent in glTF). In most cases, you should not do this, rather set initial camera by TCastleCamera inside TCastleViewport.
Make sure the Viewpoint node in X3D (default camera) indicates +Y as the up vector. This is the default X3D value. You can always just remove the Blender’s camera and setup the default camera position by code.
You can also set the viewpoint using the Castle Model Viewer feature "Clipboard → Print Current Camera (Viewpoint)". Paste the generated Viewpoint code into your X3D file (or into an X3D "wrapper" file, that includes another X3D using the Inline node).
Leave TCastleTransform.DefaultOrientation at the default value: otUpYDirectionZ (best for glTF export). Also otUpYDirectionMinusZ (best for X3D export) indicates +Y up. The point is: a value like otUpYDirection*.
If you want to follow "+Z axis is up" convention:
When exporting from Blender (levels, creatures etc.), always select to not rotate the model, i.e. keep Blender’s original coordinate system.
If you use Blender glTF exporter, just uncheck the "+Y Up" checkbox when exporting.
If you use Blender X3D exporter, set in the exporter settings:
Forward = Y Forward
Up = Z Up
Optional: This step only matters if you use deprecated TCastleRootTransform.MainScene and TCastleViewport.AutoCamera and you set the initial camera by information in the file (like TViewpointNode in X3D or equivalent in glTF). In most cases, you should not do this, rather set initial camera by TCastleCamera inside TCastleViewport.
Make sure you use Castle Model Viewer (or other VRML/X3D editor) to generate a Viewpoint in your level that makes gravity working in the Z axis. Place this in an X3D file. If you export to glTF, then add a "wrapper" X3D file with such Viewpoint node and use Inline node to refer to your glTF model from this wrapper X3D.
You can set the viewpoint using the Castle Model Viewer feature "Clipboard → Print Current Camera (Viewpoint)", just make sure to set earlier the "Navigation → Set Up (and Gravity Up) +Z".
Set TCastleTransform.DefaultOrientation := otUpZDirectionMinusY.
There are two common conventions for the "up" vector:
Most 3D modeling software, like Blender, prefers the "up" vector to be +Z.
This is natural if you think about a level map spread on the XY plane. The Z coordinate is representing the height above the ground.
glTF, X3D, default OpenGL camera, and various game engines (Castle Game Engine, Unity3d, Unreal Engine) by default prefer the "up" vector to be +Y.
This makes sense if you think about the screen as being the XY plane. Then if you look straight (in the right-hand coordinate system, as used by X3D, OpenGL and Castle Game Engine) you look in the -Z direction.
One argument in favor of this convention is that the default camera makes sense for both 2D and 3D games. For 2D games, X goes to the right, Y goes up, and Z doesn’t matter (or is used to position layers relative to each other). For 3D games, again X goes to the right, again Y goes up, and Z represents the depth. When your game character jumps, the Y coordinate increases — whether it’s a 2D or 3D game.
As you can imagine, other conventions are possible, as you can pick any 3D vector as "up", and pick anything orthogonal to it as "direction".
While our engine defaults to the convention "+Y is up", it is actually configurable:
Following the X3D standard about X3DViewpointNode, the gravity is working along the negative Y-axis of the coordinate system of the currently bound X3DViewpointNode node.
Our TCastleCamera.GravityUp is also by default +Y.
Optional: This note only matters if you use deprecated TCastleRootTransform.MainScene and TCastleViewport.AutoCamera and you set the initial camera by information in the file (like TViewpointNode in X3D or equivalent in glTF). In most cases, you should not do this, rather set initial camera by TCastleCamera inside TCastleViewport.
You can set the viewpoint using the Castle Model Viewer feature "Clipboard → Print Current Camera (Viewpoint)". Before doing it, you can use the "Navigation → Set Up (and Gravity Up) …" menu item. The generated Viewpoint node will have correct settings.
To change the TCastleCamera settings, you can set the vector TCastleCamera.GravityUp, or use the TCastleCamera.SetView method with an explicit GravityUp parameter.
To make things work smoothly, you usually want to use the same conventions for "up" throughout your asset creation process. Be wary of this when creating TCastleTransform instances in the engine, when exporting 3D models from Blender, when setting viewpoint (with gravity) in whatever way etc.
Note that Blender (and other 3D modeling software?) by default rotates models when exporting to X3D, to turn +Z into +Y. On one hand, this means that some things will "just work" (you use +Z convention inside Blender, and you get +Y convention inside VRML/X3D). On the other hand, this may create a little confusion if you manually probe some positions in Blender model and type them in X3D code (or ObjectPascal code using our engine): since Blender rotated the models, we necessarily "see" a different coordinate system than what you see in Blender.
For this reason, you may decide to disable this "rotation on export" feature, and instead decide to work with VRML/X3D files where +Z is "up".
|
Note
|
Optional: This note only matters if you use deprecated As for viewpoint in the 3D file: X3D is flexible in this regard: although the default is to have up in +Y, the specification says that up is +Y transformed by the You can setup your camera in Castle Model Viewer, use "Navigation → Set Up (and Gravity Up) …", then use "Clipboard → Print Current Camera…" option, and copy-paste the generated code from the console to your VRML/X3D file. This will set a |
The notion of direction/up is used by our engine in two places:
Gravity pulls things (player, items, creatures…) down in the -up vector. We use TCastleCamera.GravityUp of the active camera for this.
If you use TCastleTransform.Direction and TCastleTransform.Up properties to rotate your models (which is the most natural way to transform creatures, player, and items) then they need to know what is your default orientation. That is, how does the model look like when rotation is at zero.
You configure this using the TCastleTransform.Orientation property.
Usually, you want to just set TCastleTransform.DefaultOrientation, and then it will be used for all your models.
I’m glad you asked. Of course, things are never easy and there are 2 competing choices for this (that you may indeed encounter).
Default Blender X3D exporter uses one convention:
Blender up (+Z) turns into +Y,
Blender forward turns into -Z (negative Z).
Default Blender glTF, and Wavefront OBJ and other exporters use a different convention:
Blender up (+Z) turns into +Y,
Blender forward turns into +Z (positive Z).
So they both rotate to make up be "+Y", but they rotate in different ways, producing different results for what happens with model "front" (assuming you used Blender’s default suggested orientation for "front").
To account for this, and keep TCastleTransform.Direction working in an intuitive way, you can adjust TCastleTransform.Orientation or even TCastleTransform.DefaultOrientation. By default they match Blender’s glTF exporter.
To improve this documentation just edit this page and create a pull request to cge-www repository.