# Rotation trouble

**URL:** https://forum.castle-engine.io/t/rotation-trouble/831
**Category:** Uncategorized
**Created:** [June 23, 2023, 10:48pm UTC](https://forum.castle-engine.io/t/rotation-trouble/831 "2023-06-23T22:48:22Z")
**Posts on this page:** 7
**Page:** 1

<div class="post-metadata">

### Author: ![edj](https://forum.castle-engine.io/user_avatar/forum.castle-engine.io/edj/32/1701_2.png) [@edj](https://forum.castle-engine.io/u/edj)
#### Post date: [June 23, 2023, 10:48pm UTC](https://forum.castle-engine.io/t/rotation-trouble/831/1 "2023-06-23T22:48:23Z")

</div>

In my procedural trees, each node has a rotation (around the parent branch) and angle (from the parent branch) I use CalcRotationVector below:

```auto
function RotateVectorY(const Vector: TVector3;
                            Angle : Single) : TVector3;
{ rotate around Y axis, used for determining rotation axis on rotates }
var CosTheta, SinTheta: Single;
begin
 // Calculate the cosine and sine of the angle
 SinCos(Angle, CosTheta, SinTheta);
 // Apply the rotation matrix
 Result := Vector;
 Result.X := Vector.X * CosTheta + Vector.Z * SinTheta;
 Result.Z := -Vector.X * SinTheta + Vector.Z * CosTheta;
end;                     

function CalcRotationVector( angle, rotate : single ) : TVector4;
                                              var RotationAxis : TVector3;
                                              AngleAxis : TVector3;
 begin
   RotationAxis := RotateVectorY(Vector3(0, 0, 1), rotate);
   Result := Vector4(RotationAxis.X, RotationAxis.Y, RotationAxis.Z, angle);
 end;

```

to calculate the rotation vector to set the branch’s transform.rotation to. Works great.

Now I have added animals. They also have a rotation (heading) and angle (forward/backward, as they go up down terrain). I use the same function. But with the animals, the heading value is ignored. I only see the angle forward/back on the terrain. They are always facing toward direction 0. Can you see anything wrong with what I am doing here?

---

<div class="post-metadata">

### Author: ![edj](https://forum.castle-engine.io/user_avatar/forum.castle-engine.io/edj/32/1701_2.png) [@edj](https://forum.castle-engine.io/u/edj)
#### Post date: [June 23, 2023, 11:18pm UTC](https://forum.castle-engine.io/t/rotation-trouble/831/2 "2023-06-23T23:18:03Z")

</div>

I figured it out with a little help from chatgpt. This works:

```auto
function CombineRotations(const Quaternion1, Quaternion2: TQuaternion): TQuaternion;
begin
  Result := Quaternion1 * Quaternion2;
end;

function CalcRotationVector( angle, rotate : single ) : TVector4;
 var r1, r2 : TVector4;
     q1, q2, qc : TQuaternion;
     axis : TVector3;
 begin
   q1 := QuatFromAxisAngle(Vector3(0, 1, 0), rotate );
   q2 := QuatFromAxisAngle(Vector3(1, 0, 0), angle );
   qc := q1 * q2;
   qc.ToAxisAngle(Axis, angle);
   Result := Vector4( Axis.x, axis.y, axis.z, angle );
 end;               

```

ChatGPT knows castle game engine!

---

<div class="post-metadata">

### Author: ![michalis](https://forum.castle-engine.io/user_avatar/forum.castle-engine.io/michalis/32/3_2.png) [@michalis](https://forum.castle-engine.io/u/michalis)
#### Post date: [June 24, 2023, 2:18am UTC](https://forum.castle-engine.io/t/rotation-trouble/831/3 "2023-06-24T02:18:24Z")

</div>

Cool!

The 2nd version is also a bit clearer to me – that is indeed how you combine rotations, by multiplying quaternions.

Another solution could also be a deeper hierarchy: you can place TCastleTransform with 1 rotation under another TCastleTransform with 2nd rotation etc. The transformation hierarchy can have any depth, anything to be comfortable to use.

> [@edj](#):
>
> `Result := Vector4( Axis.x, axis.y, axis.z, angle );`

This can be shortened to

> [@edj](#):
>
> `Result := Vector4( Axis, angle );`

( using dedicated overload `function Vector4(const V: TVector3; const W: Single): TVector4;` ).

> [@edj](#):
>
> ChatGPT knows castle game engine!

🙂 Yeah. I’m already accustomed to Copilot completing my code 🙂

> **[Using Sketchfab API to search and download glTF (to be integrated in Castle...](https://castle-engine.io/wp/2023/05/26/using-sketchfab-api-to-search-and-download-gltf-to-be-integrated-in-castle-game-engine/)**
>
> This was super-fun and super-quick to develop (thanks to GitHub Copilot) :) I present a sample application that searches Sketchfab and downloads glTF model matching given query string. For extra ef…

> **[My mind is blown. I can use AI to generate Castle Game Engine code to...](https://castle-engine.io/wp/2022/12/17/my-mind-is-blown-i-can-use-ai-to-generate-castle-game-engine-code-to-integrate-it-with-physx-i-can-use-ai-to-generate-html-documentation-from-comments-in-pascal-code/)**
>
> My mind is completely blown by the capabilities of OpenAI chat bot ChatGPT. It can tell jokes, invent stories and protagonists, write documents with game pitches, play an RPG game with you, pretend…

---

<div class="post-metadata">

### Author: ![edj](https://forum.castle-engine.io/user_avatar/forum.castle-engine.io/edj/32/1701_2.png) [@edj](https://forum.castle-engine.io/u/edj)
#### Post date: [June 24, 2023, 4:42pm UTC](https://forum.castle-engine.io/t/rotation-trouble/831/4 "2023-06-24T16:42:30Z")

</div>

Thanks for the tips. It is working with the quaternions, I don’t want to add a transform because want to keep these animals as light as possible so there can be many. Is there a way to ask a TCastleScene how much memory it requires? I have already found some animals that give me out of heap memory just loading them. Is the killer the textures? Or the polycount?

---

<div class="post-metadata">

### Author: ![michalis](https://forum.castle-engine.io/user_avatar/forum.castle-engine.io/michalis/32/3_2.png) [@michalis](https://forum.castle-engine.io/u/michalis)
#### Post date: [June 27, 2023, 12:24pm UTC](https://forum.castle-engine.io/t/rotation-trouble/831/5 "2023-06-27T12:24:16Z")

</div>

> [@edj](#):
>
> Is there a way to ask a TCastleScene how much memory it requires? I have already found some animals that give me out of heap memory just loading them. Is the killer the textures? Or the polycount?

( To anyone that finds this thread: the memory usage talk moved to this thread: [Memory use of models](https://forum.castle-engine.io/t/memory-use-of-models/833) ).

---

<div class="post-metadata">

### Author: ![Arioch](https://forum.castle-engine.io/user_avatar/forum.castle-engine.io/arioch/32/689_2.png) [@Arioch](https://forum.castle-engine.io/u/Arioch)
#### Post date: [July 9, 2023, 10:31am UTC](https://forum.castle-engine.io/t/rotation-trouble/831/6 "2023-07-09T10:31:41Z")

</div>

I can’t help reminding of my `.RotationAngle` property

`CalcRotationVector( angle, rotate : single )`

You see, on the conceptual level the vector (direction) and the angle are still different things and have to be reasoned about as different entities. And there are cases (like simple joints) where you would not ever change the once calculated vector, only angles, having explicit access top angle-and-only-angle would make a less error-pronce and easier to use API 😃

---

<div class="post-metadata">

### Author: ![michalis](https://forum.castle-engine.io/user_avatar/forum.castle-engine.io/michalis/32/3_2.png) [@michalis](https://forum.castle-engine.io/u/michalis)
#### Post date: [July 9, 2023, 6:09pm UTC](https://forum.castle-engine.io/t/rotation-trouble/831/8 "2023-07-09T18:09:57Z")

</div>

> [@Arioch](#):
>
> I can’t help reminding of my `.RotationAngle` property
> 
> `CalcRotationVector( angle, rotate : single )`
> 
> You see, on the conceptual level the vector (direction) and the angle are still different things and have to be reasoned about as different entities. And there are cases (like simple joints) where you would not ever change the once calculated vector, only angles, having explicit access top angle-and-only-angle would make a less error-pronce and easier to use API 😃

To deconstruct / construct between axis+angle rotation represented as 3D + float and 4D we already have functionality at TVector4 API level. Here are various things you can do:

```delphi
var
  Rotation: TVector4;
  RotationAxis: TVector3;
  RotationAngle: Single;
begin
  Rotation := MyTransform.Rotation;
...
  RotationAxis := Rotation.XYZ;
  RotationAngle := Rotation.W;
  RotationAngle += RotationSpeed * SecondsPassed;
  Rotation := Vector4(RotationAxis, RotationAngle);
...
  MyTransform.Rotation := Vector4(
    MyTransform.Rotation.XYZ, 
    MyTransform.Rotation.W + 
    RotationSpeed * SecondsPassed);
end;

```

As for `.RotationAngle` property (from what I recall, you proposed `TCastleTransform:RotationAngle:Single` as a shortcut for `TCastleTransform:Rotation.W`):

After thinking about it in the past I rejected it. It would be a very small convenience in some cases but it may also cause confusion. It would not be obvious does setting `RotationAngle` keep the axis unchanged? Or does it set it to `0,0,1` (natural for 2D)?

And if it keeps it unchanged, then users will also be surprised that by default, it does nothing, as axis is zero.

Experience shows that such “convenience shortcuts” can effectively have negative effect on API. Better to keep things explicit.

Note that you can implement your own `.RotationAngle` (using class helper to look just like a property on `TCastleTransform`) on top of CGE if it makes sense in your game.
