Doom3world

The world is yours! Doom 3 - Quake 4 - ET:QW - Prey - Rage
It is currently Fri Jul 30, 2010 10:04 am

All times are UTC [ DST ]




Post new topic Reply to topic  [ 31 posts ]  Go to page 1, 2  Next
Author Message
 Post subject: MD5camera Export Project
PostPosted: Mon Oct 04, 2004 3:36 am 
Offline
a gun & a nice word
User avatar

Joined: Sat Jan 11, 2003 9:30 pm
Posts: 8536
Location: Orlando, FL
A working LScript Plugin has been finished...

DOWNLOAD CURRENT VERSION
http://www.pcgamemods.com/8120/
http://www.geocities.com/rich_is_bored/ ... Export.zip

Original Thread:

Okay, to get the ball rolling on a means to export MD5cameras from Lightwave, I'm creating this thread.

First and foremost, contrary to popular belief, I am not a programmer. I took a class on Turbo Pascal in high school 6 years ago but that's about the extent of my programming knowledge.

I've got a copy of Dev-C++ and I've been toying with it so if it's absolutely nessecary I can write a program to do the conversion but, I'll be frank, it's going to suck and it's going to be a DOS mode program at best.

Now, on to the idea...

In another thread I mentioned the possibility of converting saved motion paths (*.mot) to MD5camera format. Both file formats are plain text and that should make the conversion fairly easy.

The first thing is to decypher the formats. So, on that note, here is what I believe the MD5 camera format is comprised of...

Code:
MD5Version 10                     // Header and Version
commandline ""                     // Command Line Parameters - Used to convert maya format

numFrames 452                     // The Number of Frames
frameRate 24                     // The Framerate
numCuts 3                     // The Number of Cuts

cuts {                        // A List of Frames Where Cuts Take Place
   110
   329
   429
}

camera {                     // A List of Key Frames
   ( -908.6940917969 -3417.0383300781 552.0170898438 ) ( -0.0069773775 0.0820536837 -0.084440738 ) 54.4321250916

   ...                     // The format for each line is as follows...

   continues on                  // (X_POS, Y_POS, Z_POS) (HEADING, PITCH, BANK) FOV

   ...

   ( -903.4814453125 -3417.0383300781 555.6039428711 ) ( -0.0068133976 0.0792509392 -0.0853850618 ) 54.4321250916
}


So, the values that an MD5camera needs ...

  • Number of Frames
  • Framerate
  • Number of Cuts
  • List of Cut Frames
  • List of Frames
  • Position on the X axis
  • Position on the Y axis
  • Position on the Z axis
  • Rotation for Heading
  • Rotation for Pitch
  • Rotation for Bank
  • Field of View

Now, here is what I believe the MOT motion file format is comprised of...

Code:
LWMO
3

NumChannels 6
Channel 0                  // X channel
{ Envelope
  1                     // Number of keys in this channel
  Key 1 0 0 0 0 0 0 0 0               // Keys (Value, Time, Incoming Curve, Tension, Continuity, Bias, NA, NA, NA)
  Behaviors 1 1                  // Pre and Post Behavior (0-Reset, 1-Constant, 2-Repeat, 3-Oscillate, 4-Offset Repeat, 5-Linear)
}
Channel 1                  // Y channel
{ Envelope
  1
  Key 2 0 0 0 0 0 0 0 0
  Behaviors 1 1
}
Channel 2                  // Z channel
{ Envelope
  1
  Key 3 0 0 0 0 0 0 0 0
  Behaviors 1 1
}
Channel 3                  // Heading channel
{ Envelope
  1
  Key 0.06981317 0 0 0 0 0 0 0 0
  Behaviors 1 1
}
Channel 4                  // Pitch Channel
{ Envelope
  1
  Key 0.08726646 0 0 0 0 0 0 0 0
  Behaviors 1 1
}
Channel 5                  // Bank Channel
{ Envelope
  1
  Key 0.10471975 0 0 0 0 0 0 0 0
  Behaviors 1 1
}


So, the values that an MOT gives us either directly or can be calculated easily ...

  • Number of Frames
  • List of Key Frames
  • Position on the X axis
  • Position on the Y axis
  • Position on the Z axis
  • Rotation for Heading
  • Rotation for Pitch
  • Rotation for Bank


Now if you compare the two you'll see that there are a couple problems.

There is no list of cuts, there is no FOV channel, and Lightwave interpolates between key frames where an MD5camera lists each frame in sequence.

You could force users to bake key frames in the graph editor. This would create the missing frames and make it easier to convert because all the calculation is already done.

The alternative isn't pretty. In order to do this manually you'd have to calculate the values for a given frame based on the curve type, tension, continuity, and bias.

Not to mention I don't know what those last three values are for and if they play a role.

As far as the cuts and FOV go, that may be do able. Is it possible to add new channels to an object in Lightwave? If so, do they get saved in a motion file?

If not, then perhaps we can use one or more of the extra fields in a MOT to fudge it if we force users to bake key frames.

The alternative is to ask the user for input and that's going to be a problem for some users.

Anyway, this is just me spilling my guts. Let's see where this goes from here.

_________________
Image Staff
Learn something today? Why not write an article about it on modwiki.net?


Last edited by rich_is_bored on Mon Oct 25, 2004 10:14 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 04, 2004 2:13 pm 
Offline
Plasma Spammer
User avatar

Joined: Fri Jun 27, 2003 11:24 pm
Posts: 2709
Location: Munich, Germany
The second triple of values in the md5camera data is the X, Y and Z value of the camera's rotation quaternion, not the heading, pitch, bank format.

I'll take a look at LScript, maybe it turns out that writing such a md5camera exporter as a layout script is not that difficult.

Bozo, if you read this please tell us if you're planning to include a md5camera exporter in your LW->md5 converter, so we don't do the same work twice. :)

_________________
Image Staff
Modelviewer | 3DSMax<->MD5 | Blender<->MD5


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Mon Oct 04, 2004 2:55 pm 
Offline
respawned 1350 times
User avatar

Joined: Thu Dec 05, 2002 2:08 pm
Posts: 1416
Good thing that users like Rich and der_ton are looking into this.. I really interested in a md5camera export for lightwave.. :thumbs up!:


Sadly, I really don't know anything regarding Lscripts, so I can offer help for beta testing things... Let me know... Let US know...

_________________
theRev is coming...


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Mon Oct 04, 2004 7:21 pm 
Offline
a gun & a nice word
User avatar

Joined: Sat Jan 11, 2003 9:30 pm
Posts: 8536
Location: Orlando, FL
Damn it der_ton. There's that word again! "quaternion"

I guess I have to do some reading....

meh! :(

_________________
Image Staff
Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 04, 2004 7:36 pm 
Offline
picked up 75 health

Joined: Fri Aug 27, 2004 5:19 pm
Posts: 77
Location: vienna, austria
maybe that helps:

Matrix and Quaternion FAQ


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 04, 2004 9:11 pm 
Offline
a gun & a nice word
User avatar

Joined: Sat Jan 11, 2003 9:30 pm
Posts: 8536
Location: Orlando, FL
No help at all but thanks for trying. I'm seeing a bunch of algorithms rather than explanations.

This is alot better...

http://www.gamedev.net/reference/articl ... le1095.asp

But I still don't have this worked out. Here's an example I was toying with but at this point I'm stumpped...

Euler to Quaternion Conversion

Code:
Qx = [ cos(a/2), (sin(a/2), 0, 0)]
Qy = [ cos(b/2), (0, sin(b/2), 0)]
Qz = [ cos(c/2), (0, 0, sin(c/2))]


So, if...

Code:
a = 90
b = 180
c = 270


Then...

Code:
Qx = [ cos(90/2), (sin(90/2), 0, 0)]
Qy = [ cos(180/2), (0, sin(180/2), 0)]
Qz = [ cos(270/2), (0, 0, sin(270/2))]


And...

Code:
Qx = [ cos(45), (sin(45), 0, 0)]
Qy = [ cos(90), (0, sin(90), 0)]
Qz = [ cos(135), (0, 0, sin(135))]


And...

Code:
Qx = [ 0.70710678118654752440084436210485, (0.70710678118654752440084436210485, 0, 0)]
Qy = [ 0, (0, 1, 0)]
Qz = [ -0.70710678118654752440084436210485, (0, 0, 0.70710678118654752440084436210485)]


And to figure out Qw I need to...

Code:
Qw = Qx * Qy * Qz


Which means I need to multiply the unit quaternions. The formula is...

Code:
Q1 * Q2 =( w1.w2 - v1.v2, w1.v2 + w2.v1 + v1*v2)


But that's only for two unit quaternions. I need to multiply three. Does...

Code:
Qw = (Qx * Qy) * Qz


... give me the same result as if I multiplied them all at once? The reason I ask is because this statement throws me off...

Quote:
Be aware that the order of multiplication is important. Quaternion multiplication is not commutative, meaning

q1 * q2 does not equal q2 * q1

_________________
Image Staff
Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 04, 2004 9:30 pm 
Offline
picked up 75 health

Joined: Fri Aug 27, 2004 5:19 pm
Posts: 77
Location: vienna, austria
think so


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 05, 2004 6:21 pm 
Offline
a gun & a nice word
User avatar

Joined: Sat Jan 11, 2003 9:30 pm
Posts: 8536
Location: Orlando, FL
Okay, well I'm done screwing with quaternions. Unless of course I can borrow a high school math teacher for a few days.

Anyway, I'm looking over the MOT format again and I realize that the rotation values are not in degrees. For instance here's the rotation portion of a MOT...

Code:
Channel 3
{ Envelope
  2
  Key 0 0 0 0 0 0 0 0 0
  Key 1.5707963 2.5 0 0 0 0 1.5706217 0 0
  Behaviors 1 1
}
Channel 4
{ Envelope
  2
  Key 0 0 0 0 0 0 0 0 0
  Key 3.1415925 2.5 0 0 0 0 3.1412435 0 0
  Behaviors 1 1
}
Channel 5
{ Envelope
  2
  Key 0 0 0 0 0 0 0 0 0
  Key 4.712389 2.5 0 0 0 0 4.7118654 0 0
  Behaviors 1 1
}


Now, the values we have here are...

Heading 1.5707963
Pitch 3.1415925
Bank 4.712389

And in Lightwave they are...

Heading 90
Pitch 180
Bank 270

WTF?

Anyway, before I even started this thread I was looking at the SDK in an attempt to find information on this but I couldn't find a section on motion files so I tried to decypher it myself.

I decided to read through it today and I noticed that the Scene files are also plain text and very similar. Infact they have a section in the SDK that pretty much explains the format of MOT files.

Take a look at this...

Quote:
Envelopes

An envelope defines a function of time. For any animation time, an envelope's parameters can be combined to generate a value at that time. Envelopes are used to store position coordinates, rotation angles, scale factors, camera zoom, light intensity, texture parameters, and anything else that can vary over time.

The envelope function is a piecewise polynomial curve. The function is tabulated at specific points, called keys. The curve segment between two adjacent keys is called a span, and values on the span are calculated by interpolating between the keys. The interpolation can be linear, cubic, or stepped, and it can be different for each span. The value of the function before the first key and after the last key is calculated by extrapolation.

In scene files, an envelope is stored in a block named Envelope that contains one or more nested Key blocks and one Behaviors block.

{ Envelope
nkeys
Key value time spantype p1 p2 p3 p4 p5 p6
Key ...
Behaviors pre post
}

The nkeys value is an integer, the number of Key blocks in the envelope. Envelopes must contain at least one Key block. The contents of a Key block are as follows.

value
The key value, a floating-point number. The units and limits of the value depend on what parameter the envelope represents.

time
The time in seconds, a float. This can be negative, zero or positive. Keys are listed in the envelope in increasing time order.

spantype
The curve type, an integer. This determines the kind of interpolation that will be performed on the span between this key and the previous key, and also indicates what interpolation parameters are stored for the key.

0 - TCB (Kochanek-Bartels)
1 - Hermite
2 - 1D Bezier (obsolete, equivalent to Hermite)
3 - Linear
4 - Stepped
5 - 2D Bezier

p1...p6
Curve parameters. The data depends on the span type.

TCB, Hermite, 1D Bezier
The first three parameters are tension, continuity and bias. The fourth and fifth parameters are the incoming and outgoing tangents. The sixth parameter is ignored and should be 0. Use the first three to evaluate TCB spans, and the other two to evaluate Hermite spans.
2D Bezier
The first two parameters are the incoming time and value, and the second two are the outgoing time and value.

The Behaviors block contains two integers.

pre, post
Pre- and post-behaviors. These determine how the envelope is extrapolated at times before the first key and after the last one.

0 - Reset
Sets the value to 0.0.
1 - Constant
Sets the value to the value at the nearest key.
2 - Repeat
Repeats the interval between the first and last keys (the primary interval).
3 - Oscillate
Like Repeat, but alternating copies of the primary interval are time-reversed.
4 - Offset Repeat
Like Repeat, but offset by the difference between the values of the first and last keys.
5 - Linear
Linearly extrapolates the value based on the tangent at the nearest key.


Now, the problem is that they don't explain how they are storing the value parameter other than saying it varies depending on what it represents. Well duh! No shit! But that doesn't explain how 1.5707963 = 90 degrees.

_________________
Image Staff
Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 05, 2004 6:53 pm 
Offline
Plasma Spammer
User avatar

Joined: Fri Jun 27, 2003 11:24 pm
Posts: 2709
Location: Munich, Germany
So the value is "3.1415925" where it should be 180? Hmm, let me think why this number seems familiar... ;)

These are radians. Convert between degrees and radians with these formulae:
deg = rad * 180 / PI
rad = deg * PI / 180

_________________
Image Staff
Modelviewer | 3DSMax<->MD5 | Blender<->MD5


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Tue Oct 05, 2004 7:13 pm 
Offline
Site Admin
User avatar

Joined: Tue May 28, 2002 6:17 pm
Posts: 10185
Location: Munich / Germany
der_ton wrote:
So the value is "3.1415925" where it should be 180? Hmm, let me think why this number seems familiar... ;)

These are radians. Convert between degrees and radians with these formulae:
deg = rad * 180 / PI
rad = deg * PI / 180


Oh god, another "Dan Brown" style "messages hidden in numbers" guy... :)

_________________
Image Staff - The world is yours, soon in 6 degrees of freedom!
Visit ModWiki


Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 05, 2004 7:18 pm 
Offline
a gun & a nice word
User avatar

Joined: Sat Jan 11, 2003 9:30 pm
Posts: 8536
Location: Orlando, FL
Image

:P

_________________
Image Staff
Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 06, 2004 12:06 am 
Offline
Plasma Spammer
User avatar

Joined: Fri Jun 27, 2003 11:24 pm
Posts: 2709
Location: Munich, Germany
Here's a very simple script that dumps camera info into a file for frames 1 to 10. Unfortunately the values are all identical even for an animated camera, I'm not sure what I'm doing wrong.
Anyway, if that problem is solved, it's just a small step to a real md5camera exporter. All you need to do is convert the euler angles to quaternions, add a gui with adjustable framerange, and ofcourse format the output in md5camera syntax.

The relevant pages in the LScript reference documentation are page 115 (Camera Object Agents) and page 97 (common data members and methods for Object Agents).
Code:
@version 2.0
@warnings
@script generic


exportfile = nil; // exportfile
cam = nil; // camera that we are going to export (Camera Object Agent)


exportmd5camera
{

   exportfile.writeln("name ", cam.name, "\n");
   for (i = 1; i<=10; i++)
   {
      fovarray = cam.fovAngles(i);
      exportfile.writeln("pos ", cam.getPosition(i));
      exportfile.writeln("rot ", cam.getRotation(i));
      exportfile.writeln("fov ", fovarray[1], " ", fovarray[2], "\n");
   }
   
}

generic {
   scn = Scene();
   userobj = scn.firstSelect();
   if (userobj == nil || userobj.genus != CAMERA)
   {
      //no camera was selected, so we export the first in the scene if there is any
      userobj = Camera();
      if (userobj == nil)
      {
         info ("No camera in the scene");
         return;
      }
   }
   cam = userobj;
   exportfilename = getfile("Export File", "*.md5camera");
   if(exportfilename == nil)
      return;
   exportfile = File(exportfilename,"w");
   if(exportfile == nil)
   {
      error("Unable to open ",exportfilename);
      return;
   }
   exportmd5camera();
}

_________________
Image Staff
Modelviewer | 3DSMax<->MD5 | Blender<->MD5


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Wed Oct 06, 2004 12:34 am 
Offline
a gun & a nice word
User avatar

Joined: Sat Jan 11, 2003 9:30 pm
Posts: 8536
Location: Orlando, FL
I was initially going to try writing the program in C++ but since I'm such a noob, and you've already started writing a LScript, I'll make the switch.

EDIT: Yeah, I see what your saying. It exports two frames on my end and then just repeats itself.

Code:
name Camera

pos 0 0 -1.99997
rot 0 0 0
fov 0.789582 0.60577

pos 0 0 -4.00005
rot 0 0 0
fov 0.789582 0.60577

pos 0 0 -5
rot 0 0 0
fov 0.789582 0.60577

pos 0 0 -5
rot 0 0 0
fov 0.789582 0.60577

pos 0 0 -5
rot 0 0 0
fov 0.789582 0.60577

...

continues


EDIT AGAIN: That parameter is time and not frame. So when you say ...

Code:
   for (i = 0; i<=10; i++)
   {
      fovarray = cam.fovAngles(i);
      exportfile.writeln("pos ", cam.getPosition(i));
      exportfile.writeln("rot ", cam.getRotation(i));
      exportfile.writeln("fov ", fovarray[1], " ", fovarray[2], "\n");
   }


... and increment i your really telling it to export the status of the camera from 1 second to 10.

So, when the animation is less than 10 seconds, the last frame is repeatedly exported.

_________________
Image Staff
Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 06, 2004 1:41 am 
Offline
a gun & a nice word
User avatar

Joined: Sat Jan 11, 2003 9:30 pm
Posts: 8536
Location: Orlando, FL
Okay, I sorted it out and here is the updated code...

Code:
@version 2.0
@warnings
@script generic


exportfile = nil; // exportfile
cam = nil; // camera that we are going to export (Camera Object Agent)


exportmd5camera
{
    // Get the fps, starting, and ending frames from the scene.
   scn = Scene();
   s_fps = scn.fps;
   s_start = scn.framestart;
   s_end = scn.frameend;
   exportfile.writeln("name ", cam.name, "\n");
   count = s_start;
   i = 0;
   while (count <= s_end){
      i = count / s_fps;        // Increment the time according to the fps.
      exportfile.writeln("frame ", count);
      exportfile.writeln("time ", i);
      fovarray = cam.fovAngles(i);
      exportfile.writeln("pos ", cam.getPosition(i));
      exportfile.writeln("rot ", cam.getRotation(i));
      exportfile.writeln("fov ", fovarray[1], " ", fovarray[2], "\n");
      count++;
   }
}

generic {
   scn = Scene();
   userobj = scn.firstSelect();
   if (userobj == nil || userobj.genus != CAMERA)
   {
      //no camera was selected, so we export the first in the scene if there is any
      userobj = Camera();
      if (userobj == nil)
      {
         info ("No camera in the scene");
         return;
      }
   }
   cam = userobj;
   exportfilename = getfile("Export File", "*.md5camera");
   if(exportfilename == nil)
      return;
   exportfile = File(exportfilename,"w");
   if(exportfile == nil)
   {
      error("Unable to open ",exportfilename);
      return;
   }
   exportmd5camera();
}


I'm going to stop at this point and get back to this tommorow.

_________________
Image Staff
Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 06, 2004 1:38 pm 
Offline
Plasma Spammer
User avatar

Joined: Fri Jun 27, 2003 11:24 pm
Posts: 2709
Location: Munich, Germany
I've added md5-formatted output and the euler->quaternion conversion.
Now all there is to do is to get the camera rotated right, by swizzling/negating the euler angles before the quaternion is calculated. This would best be done by trial&error, because it can be confusing to try to get it right by thinking it through deterministically. That's because Doom3 uses a different coordinate system than LW, and because cameras are not oriented in the same way as in D3 (md5 cameras look down their x-axis, z is up, in LW they are looking down their z-axis, y is up).

Code:
@version 2.0
@warnings
@script generic


exportfile = nil; // exportfile
cam = nil; // cam that we are going to export (Camera Object Agent)

exportmd5camera
{
   scn = Scene();
   s_fps = scn.fps;
   s_start = scn.framestart;
   s_end = scn.frameend;
   
   exportfile.writeln("MD5Version 10");
   exportfile.writeln("commandline \"\"\n");
   exportfile.writeln("numFrames ", s_end-s_start+1);
   exportfile.writeln("frameRate ", s_fps);
   exportfile.writeln("numCuts 0\n");
   exportfile.writeln("cuts {\n}\n");
   exportfile.writeln("camera {\n");
   
   for (i = s_start; i<=s_end; i++)
   {
      fovarray = cam.fovAngles(i/s_fps);
      rot=cam.getRotation(i/s_fps);
      pos=cam.getPosition(i/s_fps);
      pos_d3=<pos.x, pos.z, pos.y>;
      c1=cos(rot.x/360*PI);
      c2=cos(rot.y/360*PI);
      c3=cos(rot.z/360*PI);
      s1=sin(rot.x/360*PI);
      s2=sin(rot.y/360*PI);
      s3=sin(rot.z/360*PI);
      q1=s1*c2*c3-c1*s2*s3;
      q2=c1*s2*c3+s1*c2*s3;
      q3=c1*c2*s3-s1*s2*c3;
      
      exportfile.writeln("\t( ", pos_d3," ) ( ",q1, " ", q2, " ", q3, " ) ",fovarray[1]*180/PI); //maybe fovarray[2] (vertical fov) should be used?
   }
   exportfile.writeln("}");
   
}

generic {
   scn = Scene();
   userobj = scn.firstSelect();
   if (userobj == nil || userobj.genus != CAMERA)
   {
      //no camera was selected, so we export the first in the scene if there is any
      userobj = Camera();
      if (userobj == nil)
      {
         info ("No camera in the scene");
         return;
      }
   }
   cam = userobj;
   exportfilename = getfile("Export File", "*.md5camera");
   if(exportfilename == nil)
      return;
   exportfile = File(exportfilename,"w");
   if(exportfile == nil)
   {
      error("Unable to get writing access to ",exportfilename);
      return;
   }
   exportmd5camera();
}

_________________
Image Staff
Modelviewer | 3DSMax<->MD5 | Blender<->MD5


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Wed Oct 06, 2004 7:25 pm 
Offline
a gun & a nice word
User avatar

Joined: Sat Jan 11, 2003 9:30 pm
Posts: 8536
Location: Orlando, FL
I've updated the code so that it is rotates the camera correctly. I've included comments to distinguish which is the heading, pitch, and bank.

I created a map with different textures on each wall so that I could gauge the orientation of the camera. From this point I exported a test camera repeatedly. Each time I tried a different rotation and used what I seen in game to determine if the rotation was correct.

Aside from the values needing to be written in the correct order, for some reason the pitch was inverted, for instance if I told the camera to rotate up it went down. I've fixed that by multipying q2 by -1 although I'm not sure if that fix is the correct one.

At any rate, it seems to be 100% and I'm going to toy with it a bit more just to be sure.

Here's the updated code...

Code:
@version 2.0
@warnings
@script generic


exportfile = nil; // exportfile
cam = nil; // cam that we are going to export (Camera Object Agent)

exportmd5camera
{
   scn = Scene();
   s_fps = scn.fps;
   s_start = scn.framestart;
   s_end = scn.frameend;
   
   exportfile.writeln("MD5Version 10");
   exportfile.writeln("commandline \"\"\n");
   exportfile.writeln("numFrames ", s_end-s_start+1);
   exportfile.writeln("frameRate ", s_fps);
   exportfile.writeln("numCuts 0\n");
   exportfile.writeln("cuts {\n}\n");
   exportfile.writeln("camera {\n");
   
   for (i = s_start; i<=s_end; i++)
   {
      fovarray = cam.fovAngles(i/s_fps);
      rot=cam.getRotation(i/s_fps);
      pos=cam.getPosition(i/s_fps);
      pos_d3=<pos.x, pos.z, pos.y>;
      c1=cos(rot.x/360*PI);
      c2=cos(rot.y/360*PI);
      c3=cos(rot.z/360*PI);
      s1=sin(rot.x/360*PI);
      s2=sin(rot.y/360*PI);
      s3=sin(rot.z/360*PI);
      q1=s1*c2*c3-c1*s2*s3; //bank
      q2=c1*s2*c3+s1*c2*s3; //pitch
      q3=c1*c2*s3-s1*s2*c3; //heading

      // invert q2 because it rotates up when it should look down
      q2=q2*-1;

      // User should set camera aspect ratio to 1:1 so that fovarray[1] and fovarray[2] are the same?
      exportfile.writeln("\t( ", pos_d3," ) ( ",q3, " ", q2, " ", q1, " ) ",fovarray[1]*180/PI);

   }
   exportfile.writeln("}");
   
}

generic {
   scn = Scene();
   userobj = scn.firstSelect();
   if (userobj == nil || userobj.genus != CAMERA)
   {
      //no camera was selected, so we export the first in the scene if there is any
      userobj = Camera();
      if (userobj == nil)
      {
         info ("No camera in the scene");
         return;
      }
   }
   cam = userobj;
   exportfilename = getfile("Export File", "*.md5camera");
   if(exportfilename == nil)
      return;
   exportfile = File(exportfilename,"w");
   if(exportfile == nil)
   {
      error("Unable to get writing access to ",exportfilename);
      return;
   }
   exportmd5camera();
}

_________________
Image Staff
Learn something today? Why not write an article about it on modwiki.net?


Last edited by rich_is_bored on Wed Oct 06, 2004 7:57 pm, edited 2 times in total.

Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 06, 2004 7:44 pm 
Offline
Plasma Spammer
User avatar

Joined: Fri Jun 27, 2003 11:24 pm
Posts: 2709
Location: Munich, Germany
Hmm, I would have found it alot cleaner if you had done the manipulations to the euler angles instead of the quaternion results (negating/swizzling rot.x/y/z before they are used in the quaternion conversion), but hey, that's totally irrelevant if we end up with a working script. ;)

And q1, q2 and q3 are not bank, pitch heading. These are terms that apply to the euler angles.

_________________
Image Staff
Modelviewer | 3DSMax<->MD5 | Blender<->MD5


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Wed Oct 06, 2004 8:08 pm 
Offline
a gun & a nice word
User avatar

Joined: Sat Jan 11, 2003 9:30 pm
Posts: 8536
Location: Orlando, FL
It works great. I can keyframe movement and rotation no problem. :)

The only issue is that if I were to for instance, target the camera at a null, the orientation of the camera is affected in Lightwave but this does not effect the MD5camera.

This isn't a problem with the LScript though because I had the same issue trying to export motion paths. I'm sure there is a way to keyframe that kind of motion and I know if keyframed it would carry over into Doom 3.

The only thing left is to implement some way of performing cuts. Of course that isn't something you can keyframe so the only way to do it is to ask the user for a list of keys.

_________________
Image Staff
Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Oct 06, 2004 8:16 pm 
Offline
Plasma Spammer
User avatar

Joined: Fri Jun 27, 2003 11:24 pm
Posts: 2709
Location: Munich, Germany
Maybe there's a way to bake constraint motion into keyframes, like you can do in Blender?

The FOV thingy is alright as it is, because Doom3's FOV denotes the horizontal FOV, too. The horizontal and vertical FOV are usually different, except if you have a camera that records a square-shaped image.

_________________
Image Staff
Modelviewer | 3DSMax<->MD5 | Blender<->MD5


Top
 Profile E-mail  
 
 Post subject:
PostPosted: Thu Oct 07, 2004 2:14 am 
Offline
a gun & a nice word
User avatar

Joined: Sat Jan 11, 2003 9:30 pm
Posts: 8536
Location: Orlando, FL
There is a guy who wrote a plugin called Transmotion or something that does just that. But, I'm not condoning people download it just for this.

Anyway, I've found a solution.

Instead of using getPostition and getRotation you use getWorldPosition and getWorldRotation.

Now, I can rig a camera up however I please but sometimes the values that are exported are in scientific notation (i.e -1.47128e-006).

I have to come up with a way to force the program to export decimal notation. I have a few ideas and I'll try them out and see how it goes.

On a side note there is another problem. It's not exporting the correct number of frames. It could be this isn't gathering the correct values...

Code:
   scn = Scene();
   s_fps = scn.fps;
   s_start = scn.framestart;
   s_end = scn.frameend;


Anyway, I'll be sorting both of these issues out tonight and if I find solutions I'll post an update.

_________________
Image Staff
Learn something today? Why not write an article about it on modwiki.net?


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 31 posts ]  Go to page 1, 2  Next

All times are UTC [ DST ]


Who is online

Users browsing this forum: No registered users and 0 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group