{"id":1606,"date":"2016-10-25T03:22:48","date_gmt":"2016-10-25T03:22:48","guid":{"rendered":"http:\/\/www.migenius.com\/?p=1606"},"modified":"2016-10-25T03:44:26","modified_gmt":"2016-10-25T03:44:26","slug":"3d-transformations-part-2-srt","status":"publish","type":"post","link":"https:\/\/www.migenius.com\/articles\/3d-transformations-part-2-srt","title":{"rendered":"3D Transformations – Part 2 SRT"},"content":{"rendered":"

In this, the second part of our article on transformations I will introduce SRT (Scaling, Rotation, Translation) transformations. Unlike the previous article, this one will have a lot less maths and shows you a simpler way to work with transformations in RealityServer. Additionally the method allows for automatic interpolation of transformations over time in a smooth way which is great for creating animations. Once things are moving you can also introduce motion blur for more realistic results. Read on to discover the ease of SRT transformations.<\/p>\n

<\/p>\n

Before We Start<\/h3>\n

This article assumes you have at least skimmed the previous part of this article, 3D Transformations – Part 1 Matrices<\/a>. While you don’t need to fully understand the matrix transformations, we will be using the same example scene code for this article. So, it is not repeated here, please review the previous article for the commands needed to create the base scene.<\/p>\n

As with the previous part of this article, all angles are expressed in radians<\/a> rather than degrees. You might remember the simple formula for converting degrees to radians.<\/p>\n\n\"\n\n

The examples in this article are the raw JSON-RPC command sequences that get sent to RealityServer. If you have not done so already please read the article on Exploring the RealityServer JSON-RPC API<\/a>.<\/p>\n

Translation<\/h3>\n

Like last time, let’s start with the simplest type of transformation first, translations. With SRT based transformations there is no need to specify an entire matrix, we instead specify the actual type of transformation we are doing and the values that drive it.<\/p>\n

So for example, if you want to move your object 1 unit in the x<\/span><\/em> direction, -2 units in the y<\/span><\/em> direction and 0.5 units in the z<\/span><\/em> direction we would use the command shown below. Note that like matrix transformations we still must past the values negated.<\/p>\n

You can omit the resize<\/em> parameter of the command as it defaults to true. Leave it on as it will automatically handle various things for you (more on that when we get to animations). For now just leave time_index<\/em> and transform_index<\/em> at 0 since we are not using time and only have a single transformation element. Later we will see how to use multiple elements. For now, here is how to do the translation.<\/p>\n

\r\n{\r\n  "jsonrpc": "2.0",\r\n  "method": "instance_set_transformation",\r\n  "params": {\r\n    "instance_name" : "exBoxInstance",\r\n    "resize" : true,\r\n    "time_index" : 0,\r\n    "transform_index" : 0,\r\n    "transformation" : {\r\n      "type" : "translation",\r\n      "element" : [-1,2,-0.5]\r\n    }\r\n  },\r\n  "id": 1000\r\n}\r\n<\/pre>\n<\/div><\/div>
\n
\n
Transformed<\/div>\n

\"Translation\"<\/p>\n<\/div>\n

\n
Original<\/div>\n

\"Original\"<\/p>\n<\/div>\n<\/div>\n<\/div><\/div><\/div>\n

Rotations<\/h3>\n

Rotations are where the the ease of SRT transformations really start to show. You specify them as four floating point numbers, the first three specify the axis for rotation and the forth the rotation angle (in radians). So, the one method can be used for both orthogonal axis rotations as well as arbitrary ones.<\/p>\n

Let’s do a quick example. We’ll rotate 45\u00b0 in the x<\/span><\/em> axis (1,0,0). So that will be 0.7853981634 radians. Again, we must negate our angles before passing them to our transformation. The command for applying this is below. Rotating around other axis are equally easy.<\/p>\n

\r\n{\r\n  "jsonrpc": "2.0",\r\n  "method": "instance_set_transformation",\r\n  "params": {\r\n    "instance_name" : "exBoxInstance",\r\n    "resize" : true,\r\n    "time_index" : 0,\r\n    "transform_index" : 0,\r\n    "transformation" : {\r\n      "type" : "rotation",\r\n      "element" : [1,0,0,-0.7853981634]\r\n    }\r\n  }, \r\n  "id": 1000\r\n}\r\n<\/pre>\n<\/div><\/div>
\n
\n
Transformed<\/div>\n

\"Rotation<\/p>\n<\/div>\n

\n
Original<\/div>\n

\"Original\"<\/p>\n<\/div>\n<\/div>\n<\/div><\/div><\/div>\n

Scaling<\/h3>\n

Scaling like before is very simple, even more so with SRT. You will need to invert your scale factors just as we do with matrix based scaling. For a quick example let’s scale by 1.25 in the x<\/span><\/em> axis, 4 in the y<\/span><\/em> axis and 0.5 in the z<\/span><\/em> axis. This is obviously a non-uniform scaling. Note that negative scales will mirror your object. Below is the command needed for scaling.<\/p>\n

\r\n{\r\n  "jsonrpc": "2.0",\r\n  "method": "instance_set_transformation",\r\n  "params": {\r\n    "instance_name" : "exBoxInstance",\r\n    "resize" : true,\r\n    "time_index" : 0,\r\n    "transform_index" : 0,\r\n    "transformation" : {\r\n      "type" : "scaling",\r\n      "element" : [0.8,0.25,2]\r\n    }\r\n  },\r\n  "id": 1000\r\n}\r\n<\/pre>\n<\/div><\/div>
\n
\n
Transformed<\/div>\n

\"Scaling\"<\/p>\n<\/div>\n

\n
Original<\/div>\n

\"Original\"<\/p>\n<\/div>\n<\/div>\n<\/div><\/div><\/div>\n

Combining Transformations<\/h3>\n

This is where SRT really does some magic. It becomes much simpler to combine sequences of transformation types together in any way you like to, without having to deal with matrix multiplication or other issues. You simply list them all and combining them will be taken care of for you. Note that like working with matrix transformations though, order is important. Let’s take our translation example and just for the same of it break it up into a series of three translations. It would look like this.<\/p>\n

\r\n{\r\n  "jsonrpc": "2.0",\r\n  "method": "instance_set_transformations",\r\n  "params": {\r\n    "instance_name" : "exBoxInstance",\r\n    "change_types" : true,\r\n    "resize" : true,\r\n    "time_index" : 0,\r\n    "transformations" : [\r\n      {\r\n        "type" : "translation",\r\n        "element" : [-1,0,0]\r\n      },\r\n      {\r\n        "type" : "translation",\r\n        "element" : [0,2,0]\r\n      },\r\n      {\r\n        "type" : "translation",\r\n        "element" : [0,0,-0.5]\r\n      }\r\n    ]\r\n  },\r\n  "id": 1000\r\n}\r\n<\/pre>\n<\/div><\/div>
\n
\n
Transformed<\/div>\n

\"Scaling\"<\/p>\n<\/div>\n

\n
Original<\/div>\n

\"Original\"<\/p>\n<\/div>\n<\/div>\n<\/div><\/div><\/div>\n

So we first translate by 1 unit in the x direction, then -2 units in the y direction followed by 0.5 units in the z direction. Combining all of these is done for us. We can mix and match any number of transformations of different types together in a single sequence of transformations. Let’s put together the three we made earlier to do a translation followed by a rotation followed by a scaling operation.<\/p>\n

\r\n{\r\n  "jsonrpc": "2.0",\r\n  "method": "instance_set_transformations",\r\n  "params": {\r\n    "instance_name" : "exBoxInstance",\r\n    "change_types" : true,\r\n    "resize" : true,\r\n    "time_index" : 0,\r\n    "transformations" : [\r\n      {\r\n        "type" : "translation",\r\n        "element" : [-1,2,-0.5]\r\n      },\r\n      {\r\n        "type" : "rotation",\r\n        "element" : [1,0,0,-0.7853981634]\r\n      },\r\n      {\r\n        "type" : "scaling",\r\n        "element" : [0.8,0.25,2]\r\n      }\r\n    ]\r\n  },\r\n  "id": 1000\r\n}\r\n<\/pre>\n<\/div><\/div>
\n
\n
Transformed<\/div>\n

\"SRT<\/p>\n<\/div>\n

\n
Original<\/div>\n

\"Original\"<\/p>\n<\/div>\n<\/div>\n<\/div><\/div><\/div>\n

Using this approach makes working with transformations very intuitive. If you will be editing existing transformations then you might want to review the documentation for the change_types<\/em> and resize<\/em> parameters in more detail since they will affect how existing transformations are edited.<\/p>\n

Animation<\/h3>\n

Everything we have done above has just left the time_index<\/em> parameter at 0. This effectively means we are only specifying our transformations for one point in time. To create animations, we need to add transformation information at additional points in time. We can do this by creating enough time slots<\/em> to hold the transformations at the times we want. Let’s add 3 time slots so we can specify the translations at 3 points in time.<\/p>\n

\r\n{\r\n  "jsonrpc": "2.0",\r\n  "method": "instance_set_time_slot_size",\r\n  "params": {\r\n    "instance_name" : "exBoxInstance",\r\n    "count" : 3\r\n  },\r\n  "id": 1000\r\n}\r\n<\/pre>\n

Next we assign time values to each slot. These values are not in any particular unit, so it is up to you to determine how you want to make these values to shutter times used later. I tend to use seconds just because it is easy to keep track of. So I’ll put three time points in at 0.0, 0.25 and 3.0 seconds using the following command.<\/p>\n

\r\n{\r\n  "jsonrpc": "2.0",\r\n  "method": "instance_set_index_times",\r\n  "params": {\r\n    "instance_name" : "exBoxInstance",\r\n    "times" : [0.0, 0.25, 3.0]\r\n  },\r\n  "id": 1000\r\n}\r\n<\/pre>\n

We can then start using these time slots when we set our transformations by setting the time_index<\/em> parameter to point to the time we want to set the transformation to. We can then just call instance_set_transformation<\/em> and we will have nice motion transforms.<\/p>\n

\r\n{\r\n  "jsonrpc": "2.0",\r\n  "method": "instance_set_transformation",\r\n  "params": {\r\n    "instance_name" : "exBoxInstance",\r\n    "resize" : true,\r\n    "time_index" : 0,\r\n    "transform_index" : 0,\r\n    "transformation" : {\r\n      "type" : "translation",\r\n      "element" : [-1,2,-0.5]\r\n    }\r\n  },\r\n  "id": 1000\r\n},\r\n{\r\n  "jsonrpc": "2.0",\r\n  "method": "instance_set_transformation",\r\n  "params": {\r\n    "instance_name" : "exBoxInstance",\r\n    "resize" : true,\r\n    "time_index" : 1,\r\n    "transform_index" : 0,\r\n    "transformation" : {\r\n      "type" : "rotation",\r\n      "element" : [1,0,0,-0.7853981634]\r\n    }\r\n  }, \r\n  "id": 1001\r\n},\r\n{\r\n  "jsonrpc": "2.0",\r\n  "method": "instance_set_transformation",\r\n  "params": {\r\n    "instance_name" : "exBoxInstance",\r\n    "resize" : true,\r\n    "time_index" : 2,\r\n    "transform_index" : 0,\r\n    "transformation" : {\r\n      "type" : "scaling",\r\n      "element" : [0.8,0.25,2]\r\n    }\r\n  },\r\n  "id": 1002\r\n}\r\n<\/pre>\n

This is pretty tedious though and could get pretty messy when there is a lot of animation going on. In this case the movement from the initial transform to the second will proceed much faster than the movement from the second to the third (you’ll see why I did that a little later). While simple, its already enough to look a bit complex using the single transformation command. We have a better way to handle this using a new command. Here is how it looks.<\/p>\n

\r\n{\r\n  "jsonrpc": "2.0",\r\n  "method": "instance_set_transforms",\r\n  "params": {\r\n    "instance_name" : "exBoxInstance",\r\n    "change_types" : true,\r\n    "resize" : true,\r\n    "transforms" : [\r\n      {\r\n        "time" : 0.0,\r\n        "transforms" : [\r\n          {\r\n            "type" : "translation",\r\n            "element" : [0,0,0]\r\n          },\r\n          {\r\n            "type" : "rotation",\r\n            "element" : [0,0,0,0]           \r\n          }\r\n        ]\r\n      },\r\n      {\r\n        "time" : 1.1,\r\n        "transforms" : [\r\n          {\r\n            "type" : "translation",\r\n            "element" : [-1,2,-0.5]\r\n          },\r\n          {\r\n            "type" : "rotation",\r\n            "element" : [1,0,0,-0.7853981634]\r\n          }\r\n        ]\r\n      },\r\n      {\r\n        "time" : 3.0,\r\n        "transforms" : [\r\n          {\r\n            "type" : "translation",\r\n            "element" : [-1.25,2,0]\r\n          },\r\n          {\r\n            "type" : "rotation",\r\n            "element" : [0,0,0,0]\r\n          }\r\n        ]\r\n      }\r\n    ]\r\n  },\r\n  "id": 1000\r\n}\r\n<\/pre>\n

So, instead of calling instance_set_transformation<\/em> repeatedly with different transform_index and time_index values we can just call instance_set_transforms<\/em> and set everything at once. This handles all of the time slot creation for us and automatically puts in enough slots to hold the transforms.You might notice I had to insert rotation transforms that don’t do anything to get all of the time slots to have the same number of transforms (this is required). You might also notice that this command uses float time values rather than time indices, this is possible since it is automatically making the slots behind the scenes.<\/p>\n

Unlike matrix transforms, the above is quite readable. So we start at time 0.0 with everything at the origin with no rotation. By the time 0.5 seconds we have translated to (1,-2,0.5) and then rotated by 45\u00b0 in the x<\/span><\/em> axis (a combined transformation). Finally at time 3.0 seconds we are translated to (1.25,-2,0) and reset our rotation so the object is unrotated again. Note that all of the transformations are absolute, not relative.<\/p>\n

If we render the scene now, we will see the object at time 0.0 since we haven’t told the renderer what point in time to render yet. For that purpose we have some more special commands. Once we specify a given time to render, the transformations will be interpolated for the point in time we selected from the data that is available. So if we want to render at time 0.12 seconds for example we need to use this command first.<\/p>\n

\r\n{\r\n  "jsonrpc": "2.0",\r\n  "method": "options_set_shutter_open_close",\r\n  "params": {\r\n    "options_name" : "exOptions",\r\n    "shutter_open" : 0.12,\r\n    "shutter_close" : 0.12\r\n  },\r\n  "id": 1000\r\n}\r\n<\/pre>\n<\/div><\/div>
\n
\n
Time 0.12s<\/div>\n

\"SRT<\/p>\n<\/div>\n

\n
Time 0.00s<\/div>\n

\"Original\"<\/p>\n<\/div>\n<\/div>\n<\/div><\/div><\/div>\n

There are also individual commands for just setting the shutter open and close alone if you wish, however the vast majority of the time you will want to set both at once. You’ll notice we are setting them both to the same value for now. Now if we render repeatedly, setting a different shutter open and close time for each frame we can effectively render an animation, without having to explicitly change transformations at all.<\/p>\n

You can do this any number of ways, I just did a little shell script for that purpose, advancing the shutter open and close time by 0.04 seconds per frame to give me 25 fps. Rendering those frames give me the short animation on the right. The short burst of movement at the start looks a bit unnatural for some reason though. I wonder what would happen if we set the shutter open and close times further apart\u2026<\/p>\n<\/div><\/div>

\n
\n
Video<\/div>\n


\n