Jump to content
  • Advertisement
Sign in to follow this  
data2

OpenGL How do I port the view-matrix from opengl??

This topic is 4862 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi, I have a little opengl code implementing a maya-like camera. unfortunately, i'm note sure how to port that to DirectX. In OpenGL you have a state machine and only stacks and you simply transform the matrices. Uh, well, maybe the simplest way is to show you the code instead of trying to explain it. I've taken it from here: http://www.robthebloke.org/opengl_programming.html#4 (The "Maya 3D Camera Example"). In addition, only the cpp-code can be downloaded here: http://felix.spunited.de/tmp/foren/mayaCameraOpenGL.cpp The problem I have is that in the view-matrix (or is it world and view) is simply set in the display() method by perform the 3 transformations one by one. How am I doing all that in DirectX?

Share this post


Link to post
Share on other sites
Advertisement
as far as i understand you r looking on how to set up, and view the world?

first u set the projecttion matrix by:
D3DXMatrixPerspectiveFovLH(&Proj, m_fFieldOfView , m_fAspectRatio, m_fNear, m_fFar);
m_pD3DDevice->SetTransform(D3DTS_PROJECTION, &Proj );

then u calculate the view matrix and set that to in the device.
D3DXMatrixLookAtLH(&mView, &vPos, &vView, &vUp);
m_pD3DDevice->SetTransform(D3DTS_VIEW, &mView);

but im not quite sure if thats wat you want of not.

these will let you have a camera in the world and you can actually see your world.

you set your View matrix as you want it to be, through the position, view and up vectors in D3DXMatrixLookAtLH.

let me know if thats wat you are looking for.

Share this post


Link to post
Share on other sites
THanks for the reply. But actually, I know about matrices and how to set them up. What I'm looking for is a camera control like in Maya. Do you know Maya? Well, and then I found the OpenGL example implementing exactly the camera behavior I searched.

But unforunately, OpenGL is totally different to DirectX in how they handle matrix transformations. Have you looked at the sample code? Let me post a snippet:

float zoom = 15.0f;
float rotx = 0;
float roty = 0.001f;
float tx = 0;
float ty = 0;
int lastx=0;
int lasty=0;
unsigned char Buttons[3] = {0};

void display()
{
glClear(GL_COLOR_BUFFER_BIT|GL_DEPTH_BUFFER_BIT);

glMatrixMode(GL_MODELVIEW);
glLoadIdentity();

glTranslatef(0,0,-zoom);
glTranslatef(tx,ty,0);
glRotatef(rotx,1,0,0);
glRotatef(roty,0,1,0);

// draw grid
glBegin(GL_LINES);
for(int i=-10;i<=10;++i) {
glVertex3f(i,0,-10);
glVertex3f(i,0,10);

glVertex3f(10,0,i);
glVertex3f(-10,0,i);
}
glEnd();

glutSwapBuffers();
}

void Motion(int x,int y)
{
int diffx=x-lastx;
int diffy=y-lasty;
lastx=x;
lasty=y;

if( Buttons[0] && Buttons[1] )
{
zoom -= (float) 0.05f * diffx;
}
else
if( Buttons[0] )
{
rotx += (float) 0.5f * diffy;
roty += (float) 0.5f * diffx;
}
else
if( Buttons[1] )
{
tx += (float) 0.05f * diffx;
ty -= (float) 0.05f * diffy;
}
glutPostRedisplay();
}


How am I doing that in DirectX? Calc the Eye, Lookat and Up from the mouse movements and setting up the view-matrix so that it behaves like mentioned above.

Share this post


Link to post
Share on other sites
Hi,

You could use the D3DX library.

[SOURCE]

D3DXMatrixTranslation(matTrans, -1, 0, -1);
D3DXMatrixRotationY(matRot, alfa);//used in order to rotate the object/scene
D3DXMatrixIdentity(matWorld);
D3DXMatrixMultiply(matWorld, matWorld, matTrans);
D3DXMatrixMultiply(matWorld, matWorld, matRot);
g_pd3dDevice.SetTransform(D3DTS_WORLD, matWorld);

// Set up our view matrix. A view matrix can be defined given an eye point,
// a point to lookat, and a direction for which way is up. Here, we set the
// eye "distance" units back along the z-axis and up pan_y units, look at the
// P(0,0,100), and define "up" to be in the y-direction.
D3DXMatrixLookAtLH(matView, D3DXVector3(0, pan_y, distance),
D3DXVector3(0, 0, 100),
D3DXVector3(0.0, 1.0, 0.0));

g_pd3dDevice.SetTransform(D3DTS_VIEW, matView);

// For the projection matrix, we set up a perspective transform (which
// transforms geometry from 3D view space to 2D viewport space, with
// a perspective divide making objects smaller in the distance). To build
// a perpsective transform, we need the field of view (1/4 pi is common),
// the aspect ratio, and the near and far clipping planes (which define at
// what distances geometry should be no longer be rendered).

D3DXMatrixPerspectiveFovLH(matProj, D3DX_PI/4, 1.0, 1.0, 100.0);
g_pd3dDevice.SetTransform(D3DTS_PROJECTION, matProj);
[/SOURCE]
[/source]

[edit] use mouse delta to affect "alfa", although that is camera rotation by altering view matrix. If you need to actually rotate the object, look at ramy's example.

Something like this. The code is from an old project, you need to modify it.

DX is very similar to OpenGL, also sets states and then pushes vertices through rendering pipeline while applying matrices.

Hope this helps.

[Edited by - ttdeath on June 21, 2005 11:56:09 AM]

Share this post


Link to post
Share on other sites
i checked the exe out, thats a trackball movement.


thats easy, i have a tutorial for case.

its in http://www.ultimategameprogramming.com/index2.php

in the directX section, in one of the pages.

Share this post


Link to post
Share on other sites
It is fairly straightforward to convert OpenGL to D3DX. Here is an example:
    glLoadIdentity();
glTranslatef( x, y, z );
glRotatef( angle, axis.x, axis.y, axis.z );
The equivalent in D3D is this:
    D3DXMatrix current;
D3DXLoadIdentity( &current );

D3DXMatrix t;
D3DXMatrixTranslation( &t, x, y, z );
D3DXMatrixMultiply( &current, &t, &current );

D3DXMatrix r;
D3DXMatrixRotationAxis( &current, &axis, DEG_TO_RAD(angle) );
D3DXMatrixMultiply( &current, &r, &current );

g_pd3dDevice.SetTransform(D3DTS_whatever, &current);
Also...
    glRotatef(rotx,1,0,0); ==> D3DXMatrixRotationX( &current, DEG_TO_RAD(rotx) );
glRotatef(roty,0,1,0); ==> D3DXMatrixRotationY( &current, DEG_TO_RAD(roty) );
glRotatef(rotz,0,0,1); ==> D3DXMatrixRotationZ( &current, DEG_TO_RAD(rotz) );

Share this post


Link to post
Share on other sites
Quote:
Original post by JohnBolton
    glLoadIdentity();
glTranslatef( x, y, z );
glRotatef( angle, axis.x, axis.y, axis.z );
The equivalent in D3D is this:
    D3DXMatrix current;
D3DXLoadIdentity( &t );

D3DXMatrix t;
D3DXMatrixTranslation( &t, x, y, z );
D3DXMatrixMultiply( &t, &t, &t );

D3DXMatrix r;
D3DXMatrixRotationAxis( &t, &axis, DEG_TO_RAD(angle) );
D3DXMatrixMultiply( &t, &r, &t );

g_pd3dDevice.SetTransform(D3DTS_whatever, &t);



Some minor corrections to the D3D code:
    D3DXMATRIX current;
D3DXMatrixIdentity( ¤t );

D3DXMATRIX t;
D3DXMatrixTranslation( &t, x, y, z );
D3DXMatrixMultiply( ¤t, ¤t, &t );

//Note the removal
D3DXMatrixRotationAxis( &t, &axis, D3DXToRadian(angle) );
D3DXMatrixMultiply( ¤t, ¤t, &t );

g_pd3dDevice->SetTransform(D3DTS_whatever, ¤t); //"whatever" can be WORLD, VIEW, PROJECTION, or a couple of other obscure things


Another thing to look into is ID3DXMatrixStack which you could use like so:

LPD3DXMATRIXSTACK MatrixStack = NULL;
D3DXCreateMatrixStack(0, &MatrixStack);
MatrixStack->Push();
MatrixStack->LoadIdentity();
MatrixStack->Translate(x, y, z);
MatrixStack->RotateAxis(&axis, angle);
g_pd3dDevice->SetTransform(D3DTS_whatever, MatrixStack->GetTop()); //See above note
MatrixStack->Pop();

//Then later, to clean up
MatrixStack->Release();
MatrixStack = NULL;

The ID3DXMatrixStack object makes converting from OGL very easy!

Share this post


Link to post
Share on other sites
Hi, the trackball aproach seems to be the best for my needs. But ramy's example transforms the object's world matrix and not the view. I'll try to modify the code so that the camera is rotated around its lookat point.

Share this post


Link to post
Share on other sites
Hi,

in the last days I've implemented a camera model that suits my needs quite nice. In the DirectX Sample Framework I found the Classes Arball, Camera and ModelViewerCamera of which I basically took the arball and some of the code from the ModelViewerCamera to do the rotation and zooming. The translation i did myself.

But I have a question about the arcball. Its center is always located in the center of the client area. For a better behavior it would be preferably to have the center be located at the point where the mouse-down event occured. Could anyone (with a better understanding about spheres and the math) give me some hints how to translate the sphere's center to the mouse-down coordinates? I've tried the following with only moderate success:

I wanted to calc the offset that the mouse was clicked off the center and add it to all coordinates. That works quite nice but there is a problem in that solution: Let the offset be 300 pixels. When calculating the coordinates on the sphere the mouse coordinates are considered as outside 300 pixels too early as the edge of the window isn't reached yet. The rotation simply stops. Can I expand the radius of the sphere (currently 1.0f)? How would the computation of the coordinates will look like then?

Here is my code how it is right now. The project incl. the executable can be downloaded at: http://felix.spunited.de/tmp/foren/CameraTest.zip


using System;
using System.Drawing;
using Microsoft.DirectX;

namespace MatricesTutorial
{
public class Trackball
{
/// <summary>Matrix for track ball's orientation</summary>
protected Matrix _rotationMatrix;

/// <summary>track ball's window width</summary>
protected int _widthPixels;
/// <summary>track ball's window height</summary>
protected int _heightPixels;
/// <summary>center of track ball </summary>
protected Vector2 _centerPixels;
/// <summary>track ball's radius in screen coords</summary>
protected float _radius;

/// <summary>Quaternion before button down</summary>
protected Quaternion _downQuat;
/// <summary>Composite quaternion for current drag</summary>
protected Quaternion _currentQuat;
/// <summary>Whether user is dragging track ball</summary>
protected bool _isDragging;

/// <summary>Whether the mouse-coords are moved to the center or not.</summary>
protected bool _autoCenterMouseCoords = true;
/// <summary>The offset that the user has clicked off the center.</summary>
protected Vector2 _mouseCenterOffset = Vector2.Empty;

/// <summary>starting point of rotation arc</summary>
protected Vector3 _downPtRotation = Vector3.Empty;
/// <summary>current point of rotation arc</summary>
protected Vector3 _currentPtRotation = Vector3.Empty;


/// <summary>Gets the rotation matrix</summary>
public Matrix RotationMatrix
{
get
{
return _rotationMatrix = Matrix.RotationQuaternion(_currentQuat);
}
}


/// <summary>Resets the trackball</summary>
public void Reset()
{
_downQuat = Quaternion.Identity;
_currentQuat = Quaternion.Identity;
_rotationMatrix = Matrix.Identity;
_isDragging = false;
_radius = 1.0f;
}

/// <summary>Convert a point on the client-area to a vector</summary>
/// <param name="mouseCoords">The mouse coordinates in pixels</param>
public Vector3 ClientPointToVector(Vector2 mouseCoords)
{
float x = -(mouseCoords.X - _widthPixels / 2.0f) / (_radius * _widthPixels / 2.0f);
float y = (mouseCoords.Y - _heightPixels / 2.0f) / (_radius * _heightPixels / 2.0f);
float z = 0.0f;
float mag = (x*x) + (y*y);

// point outside the sphere => project x,y by normalize the vector
if (mag > _radius)
{
float scale = _radius / (float)Math.Sqrt(mag);
x *= scale;
y *= scale;
}
// point inside sphere => calc z
else
{
z = (float)Math.Sqrt(_radius*_radius - mag);
}

return new Vector3(x, y, z);
}

/// <summary>Set window paramters</summary>
public void SetWindow(int w, int h, float r)
{
_widthPixels = w;
_heightPixels = h;
_radius = r;
_centerPixels = new Vector2((float)w / 2.0f, (float)h / 2.0f);
}
public void SetWindow(int w, int h)
{
SetWindow(w, h, 1.0f); // default radius
}

/// <summary>Computes a quaternion from ball points</summary>
public static Quaternion QuaternionFromBallPoints(Vector3 from, Vector3 to)
{
float dot = Vector3.Dot(from, to);
Vector3 cross = Vector3.Cross(from, to);

return new Quaternion(cross.X, cross.Y, cross.Z, dot);
}

/// <summary>Begin the trackball 'dragging'</summary>
/// <param name="mouseCoords">The mouse coordinates on the client area</param>
public void OnRotationBegin(Point mouseCoords)
{
Vector2 coords = PointToVector2(mouseCoords);
CalcOffsets(coords);

PrepareMouseCoords(ref coords);

_isDragging = true;
_downQuat = _currentQuat;
_downPtRotation = ClientPointToVector(coords);
}

/// <summary>The trackball is 'moving'</summary>
/// <param name="mouseCoords">The mouse coordinates on the client area</param>
public void OnRotationMove(Point mouseCoords)
{
if (_isDragging)
{
Vector2 coords = PointToVector2(mouseCoords);

PrepareMouseCoords(ref coords);

_currentPtRotation = ClientPointToVector(coords);
_currentQuat = _downQuat * QuaternionFromBallPoints(_downPtRotation, _currentPtRotation);
}
}

/// <summary>Done dragging the trackball</summary>
public void OnRotationEnd()
{
_isDragging = false;
}


private void CalcOffsets(Vector2 mouseCoords)
{
_mouseCenterOffset = mouseCoords - _centerPixels;
}

private void PrepareMouseCoords(ref Vector2 mouseCoords)
{
if(_autoCenterMouseCoords)
{
}
}

private Vector2 PointToVector2(Point mouseCoords)
{
return new Vector2((float)mouseCoords.X, (float)mouseCoords.Y);
}
}
}

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!