[Closed] converting pos and rot values to a new matrix
given a set of point 3 values for position and rotation, and a new transform matrix, how do I convert them?
given :
pos=[1,10,25]
rot=[90,-45,20]
newMatrix=(matrix3 [-1,0,0] [0,0,1] [0,-1,0] [0,0,0])
how do I generate a new pos and rot value?
i don’t clearly understand what you want to do, but to transform position and rotation you have to multiply them by the matrix
pos = pos*tmMatrix
rot = (eulerangles rot.x rot.y rot.z)*tmMatrix
you can make original matrix from pos and rotation as:
tm = translate ((eulerangles rot.x rot.y rot.z) as matrix3) pos
Assuming the original and new values are in the same parent space:
pos=[1,10,25]
rot=[90,-45,20]
newMatrix = ((eulerangles rot.x rot.y rot.z) as matrix3) * (transmatrix pos)
result:
(matrix3 [0.664463,0.241845,0.707107] [-0.664463,-0.241845,0.707107] [0.34202,-0.939693,0] [1,10,25])
The last vector in the matrix3 is the position, so a more readable version is just:
-- set orientation
newMatrix = ((eulerangles rot.x rot.y rot.z) as matrix3)
-- set position
newMatrix[4] = pos
I’m trying to build a tool that allows the artists to position and orient game objects in Max and then convert the pos and rot data from max’s z-up left, hand coordinates space to the game’s y-up right hand coordinate space.
It’s been a problem I have been trying to solve for a while, with little success.
I will try the math you have posted and report back.
Assuming the original and new values are in the same parent space:
the original values are relative to a parent object (a bone or a mesh,) the new values are applied relative to the parent but in the new y-up right handed space. Does the parent coordinate system also need to be figured into this?
I seem to have communicated poorly. you both indicate how to turn pos and rot into a matrix, but then what? how do I pass this matrix to the game’s world transfom (matrix3 [-1,0,0] [0,0,1] [0,-1,0] [0,0,0]) and then extract pos and rot form this?
in other words:
pos=[1,10,25]
rot=[90,-45,20]
object_transform_in_max_world= ((eulerangles rot.x rot.y rot.z) as matrix3) * (transmatrix pos)
game_world_tansform= (matrix3 [-1,0,0] [0,0,1] [0,-1,0] [0,0,0])
object_transform_in_game_world=????
object_pos_in_game_world=???
object_rot_in_game_world=???
from IGame in the SDK, tells you hows transforms are arranged.
/**********************************************************************
*<
FILE: IConveriosnManager.h
DESCRIPTION: Tools to convert from one coordinate system to another
CREATED BY: Neil Hazzard
HISTORY: 10|12|2002
IGame Version: 1.122
*> Copyright (c) 2002, All Rights Reserved.
**********************************************************************/
/*!\file IConversionManager.h
\brief IGame Coordinate conversion Interfaces.
*/
#ifndef __ICONVERSIONMANAGER__H
#define __ICONVERSIONMANAGER__H
#pragma once
#include "maxheap.h"
#include "Max.h"
#include "IGameStd.h"
//!A User definable Coordinate System
/*! The developer can use this to define the Coordinate System that they are using. Rotation specifies whether
it is a Right or Left handed system. The Axis define which way the primary axis point. This will mean that the
data extracted is converted correctly, and the winding order is correct for Left and Right handed systems.
In 3ds Max this could be defined as
<pre>
UserCoord = {
1, //Right Handed
1, //X axis goes right
4, //Y Axis goes in
2, //Z Axis goes up.
1, //U Tex axis is left
0, //V Tex axis is Up
}
</pre>
*/
struct UserCoord{
//! Handedness
/*! 0 specifies Left Handed, 1 specifies Right Handed.
*/
int rotation;
//! The X axis
/*! It can be one of the following values 0 = left, 1 = right, 2 = Up, 3 = Down, 4 = in, 5 = out.
*/
int xAxis;
//! The Y axis
/*! It can be one of the following values 0 = left, 1 = right, 2 = Up, 3 = Down, 4 = in, 5 = out.
*/
int yAxis;
//! The Z axis
/*! It can be one of the following values 0 = left, 1 = right, 2 = Up, 3 = Down, 4 = in, 5 = out.
*/
int zAxis;
//! The U Texture axis
/*! It can be one of the following values 0 = left, 1 = right
*/
int uAxis;
//! The V Texture axis
/*! It can be one of the following values 0 = Up, 1 = down
*/
int vAxis;
};
//! A developer can use this class to define what Coord Systems IGame exports the data in
/*! IGame will convert data from the standard 3ds Max RH Z up system to any defined system. At the moment direct support
for DirectX and OpenGL are provided. This means that all Matrix and vertex data will have been converted ready to use
on your target system.
The coordinate system should set up straight after initialising IGame. The default is to provide everything in 3ds Max
native formats.
*/
class IGameConversionManager: public MaxHeapOperators
{
public:
//! The supported Coordinate Systems
/*! These are used to tell IGame how to format the data
*/
enum CoordSystem{
IGAME_MAX, /*!<Max RH Z up & +Y*/
IGAME_D3D, /*!<DirectX LH Y up & +Z*/
IGAME_OGL, /*!<OpenGL RH Y up & -Z*/
IGAME_USER /*!<User defined Coord System*/
};
//!Set IGame up for the Coordinate System you are wanting the data to be present in
/*! The default system is the 3ds MAX system.
\param Coord The Coordinate system to use If Coord is IGAME_USER then you must set
this data via SetUserCoordSystem
*/
virtual void SetCoordSystem(CoordSystem Coord) =0;
//!Get the Coordinate System
/*! The default system is the 3ds MAX system.
\return The current Coordinate System used, one of the IGameConversionManager::CoordSystem
*/
virtual CoordSystem GetCoordSystem() =0;
//!Set the User defined Coordinate system, if the CoordSystem has been defined as IGAME_USER
/*! Allow a user definable Coordinate System. See comments above.
\param UC THe data to define the system
*/
virtual void SetUserCoordSystem(UserCoord UC) =0;
};
//!External access to the conversion manager
IGAMEEXPORT IGameConversionManager * GetConversionManager();
#endif __ICONVERSIONMANAGER__H
so each coordinate system would be defined as…
UserCoord maxCoord = {1,1,4,2,1,0};
UserCoord D3DCoord = {0,1,2,4,1,1};
UserCoord openGLCoord = {1,1,2,5,1,1};
so to convert from max to D3D y & z is swapped at the coordinate and axis levels for max to OpenGL the same but with negated z.
so, given any (max_pos, max_rot):
--Max RH Z up to Direct 3d LH Y up
Direct3D_pos = [ max_pos.x , max_pos.z , max_pos.y ]
Direct3D_rot = [ max_rot.x , max_rot.z ,max_rot.y ]
--Max RH Z up to Open GL RH Y up & -Z
--do I invert Z after swapping Y and Z?
OpenGL_pos = [ max_pos.x, max_pos.z, -max_pos.y ]
OpenGL_rot = [ max_rot.x ,max_rot.z, -max_rot.y ]
The matrix transform conversion approach has been a bust so far, so I hope it really is that simple…
doing that with the positions is correct, but I don’t think not for the rotations… you have to convert the matrix transform then compute the new angles.
you can prove it to yourself
create a box and randomly rotate it
with it selected in the listener type & run
$.transform as eulerangle
now just
$.transform
now rearrange the matrix swapping the y & z coordinate in each point axis and then swapping the Y and Z axis.
now add
as eulerangles
after matrix and run the code, you'll find the angles are not [x,z,y] of the original angles.
in short…
max
(matrix3 [0.559368,-0.788763,0.254874] [0.828758,0.526105,-0.190718] [0.0163407,0.31791,0.94798] [0,0,0]) as eulerangles
directx
(matrix3 [0.559368,0.254874,-0.788763] [0.0163407,0.94798,0.31791] [0.828758,-0.190718,0.526105] [0,0,0]) as eulerangles
opengl
(matrix3 [0.559368,0.254874,-0.788763] [0.0163407,0.94798,0.31791] [-0.828758,0.190718,-0.526105] [0,0,0]) as eulerangle
Thanks all for the replies. please bare with me, I find Matrix stuff to be a black magic box…
not for the rotations… you have to convert the matrix transform then compute the new angles.
ok, is this what you descirbe?
fn maxToGameRot rot=
(
--rot is a point3 value here, so convert to euler, then matrix3
local maxObjMatrix = (( eulerAngles rot.x rot.y rot.z ) as matrix3 )
local gameMatrix = ( matrix3 [-1,0,0] [0,0,1] [0,-1,0] [0,0,0] )
--convert the matrix (do I have this correct?)
local gameObjMatrix = xformMat maxObjMatrix gameMatrix
--extract the angles
gameRot=gameObjMatrix as eulerAngles
return [gameRot.x,gameRot.y,gameRot.z]
),
I’ll also need to reverse this process, to convert game flavored pos & rot data into Max flavored data… would using inverse gameMatrix accomplish this?
something like that should do the trick, though the proof of the pudding in cases like this is in the eating so to speak, as all engines have quirks so you may need to tweak gamematrix to get the right results.
for the most part I use IGame and it’s conversion manager to generate positions angles and transforms in the correct system for the times where this is doesn’t cover it, some world space generated bounding boxes and viewport matrices I use this to mirror then igame conversions, its in C++ but should be easily ported to mxs
static const UserCoord maxCoord = {1,1,4,2,1,0};
static const UserCoord D3DCoord = {0,1,2,4,1,1};
static const UserCoord openGLCoord = {1,1,2,5,1,1};
static const UserCoord custom = {0,1,2,4,1,1};
class CoordsysManager
{
enum system { max, directx, opengl, cust };
system sys;
static UserCoord coordsys[8];
static Point3 axis[6];
Matrix3 xyz;
Matrix3 uvw;
public:
CoordsysManager(system s) : sys(s)
{
BuildXYZCoordSys();
BuildUVWCoordSys();
}
void BuildXYZCoordSys()
{
xyz = Matrix3(axis[coordsys[sys].xAxis], axis[coordsys[sys].yAxis], axis[coordsys[sys].zAxis], Point3(0.0f,0.0f,0.0f));
}
void BuildUVWCoordSys()
{
float um = -1.0f;
if(coordsys[sys].uAxis)
um = 1.0f;
float vm = 1.0f;
if(coordsys[sys].vAxis)
vm = -1.0f;
uvw = Matrix3(axis[1]*um, axis[4]*vm, axis[2]*vm*um, Point3(0.0f,0.0f,0.0f));
}
void ConvertXYZ(Point3& in, Point3& out) { out = xyz.VectorTransform(in); }
void ConvertUVW(Point3& in, Point3& out) { out = uvw.VectorTransform(in);}
void ConvertMatrix(Matrix3& in, Matrix3& out) { out = XFormMat(xyz, in); }
};
UserCoord CoordsysManager::coordsys[] = { maxCoord, D3DCoord, openGLCoord, custom, maxCoord, maxCoord, maxCoord, maxCoord };
Point3 CoordsysManager::axis[6] = { Point3(-1.0f,0.0f,0.0f), Point3(1.0f,0.0f,0.0f), Point3(0.0f,0.0f,1.0f),
Point3(0.0f,0.0f,-1.0f),Point3(0.0f,1.0f,0.0f), Point3(0.0f,-1.0f,0.0f)};