pipeline.cpp

00001 /*
00002 * "PS2" Application Framework
00003 *
00004 * University of Abertay Dundee
00005 * May be used for educational purposed only
00006 *
00007 * Author - Dr Henry S Fortuna
00008 *
00009 * $Revision: 1.5 $
00010 * $Date: 2007/08/27 20:22:34 $
00011 *
00012 */
00013 
00014 #include <sps2lib.h>
00015 #include <sps2tags.h>
00016 #include <sps2util.h>
00017 #include <sps2regstructs.h>
00018 #include "PS2Defines.h"
00019 #include "ps2matrix4x4.h"
00020 #include "ps2maths.h"
00021 #include "sps2wrap.h"
00022 #include "dma.h"
00023 #include "pipeline.h"
00024 
00025 
00026 // Singleton initialiser (note: Never make new copies of this classes anywhere else)
00027 CPipeline CPipeline_SingletonInit;
00028 
00029 #define ROTXMAX (PIHALF - 0.02f)
00030 
00031 CPipeline::CPipeline()
00032 {
00033         // Don't put anything in here which relies on other classes since
00034         // this class will probably be initialised first by the singleton 
00035         // instance.    
00036 }
00037 
00038 void CPipeline::Initialise(void)
00039 {
00040         m_ViewProjection = Matrix4x4::IDENTITY;
00041         m_LightDirs = Matrix4x4::IDENTITY;
00042         m_LightCols = Matrix4x4::NULLMATRIX;
00043         m_Camera = Matrix4x4::IDENTITY;
00044         m_Projection = Matrix4x4::IDENTITY;
00045         m_Scale = Vector4(2048.0f, 2048.0f, ((float)0xFFFFFF) / 32.0f, 0.0f);
00046         
00047         m_near = 2.0f;                          // Near plane
00048         m_far = 2000.0f;                        // Far plane
00049         m_FOV = 60.0f;                          // FOV
00050         m_Aspect = 4.0f / 3.0f;         // Aspect ratio
00051         
00052         m_ScreenW = sps2UScreenGetWidth();
00053         m_ScreenH = sps2UScreenGetHeight();
00054         
00055         assert((m_ScreenW > 0.0f) && (m_ScreenW > 0.0f));
00056         
00057         //printf("%f %f\n", m_ScreenW, m_ScreenH);
00058         
00059         m_CamPos = Vector4(0.0f, 0.0f, 0.0f, 1.0f);
00060         m_XRot = 0.0f;
00061         m_YRot = 0.0f;
00062         
00063         CalcProjection();
00064         
00065         m_ViewProjection = m_Camera * m_Projection;
00066         
00067         // Set ambient light on R=G=B=128
00068         m_LightCols(3,0) = 128.0f;
00069         m_LightCols(3,1) = 128.0f;
00070         m_LightCols(3,2) = 128.0f;
00071         
00072 }
00073 
00074 void CPipeline::CalcProjection(void)
00075 {
00076         float FovYdiv2 = DegToRad(m_FOV) * 0.5f; 
00077         float cotFOV = 1.0f / (Sin(FovYdiv2) / Cos(FovYdiv2));
00078         
00079         // We will be projecting to the 4096 wide drawing area
00080         // Look also at the VU projection code
00081         float w = cotFOV * (m_ScreenW / 4096.0f) / m_Aspect;
00082         float h = cotFOV * (m_ScreenH / 4096.0f);
00083 
00084         m_Projection = Matrix4x4  (w,  0, 0,                                   0,
00085                                                            0, -h, 0,                                   0,
00086                                                            0,  0, (m_far+m_near) / (m_far-m_near),    -1,
00087                                                            0,  0, (2*m_far*m_near) / (m_far-m_near),   0);
00088                                                  
00089 }
00090 
00091 
00092 void CPipeline::Update(float Strafe, float Advance, float UpDown, float XRot, float YRot)
00093 {
00094         // Process rotations
00095         m_YRot -= YRot * Abs(YRot) * 0.07f;
00096         m_XRot += XRot * Abs(XRot) * 0.07f;
00097         
00098         // Clamp xrot to prevent going upside down.
00099         if(m_XRot > ROTXMAX)
00100                 m_XRot = ROTXMAX;
00101         
00102         if(m_XRot < -ROTXMAX)
00103                 m_XRot = -ROTXMAX;
00104                 
00105         // Keep y rotation in one circle
00106         if (m_YRot >= TWOPI)    m_YRot -= TWOPI;
00107         if (m_YRot <= -TWOPI)   m_YRot += TWOPI;
00108         
00109         // Sort out the rotations
00110         Matrix4x4 roty, rotx;
00111         roty.RotationY( m_YRot );
00112         rotx.RotationX( m_XRot );
00113         Matrix4x4 CamRot = rotx * roty;
00114         
00115         // Transpose rotation matrix to get camera matrix
00116         CamRot = Transpose(CamRot);
00117 
00118         // Get the direction vectors for the camera
00119         Vector4 vXAxis = Vector4(CamRot(0,0), CamRot(1,0), CamRot(2,0), 1);
00120         Vector4 vYAxis = Vector4(CamRot(0,1), CamRot(1,1), CamRot(2,1), 1);
00121         Vector4 vZAxis = Vector4(CamRot(0,2), CamRot(1,2), CamRot(2,2), 1);
00122         
00123         // Process movement
00124         Strafe *=   0.5f;
00125         Advance *=  0.5f;
00126         UpDown *=   0.5f;
00127 
00128         // Work out the requested move for this frame
00129         Vector4 vReqMove;
00130         vReqMove =  vXAxis * Strafe;
00131         vReqMove += vYAxis * UpDown;
00132         vReqMove += vZAxis * Advance;
00133         
00134         // And add it to the camera position
00135         m_CamPos += vReqMove;
00136 
00137         // Finally build the camera matrix
00138         Matrix4x4 matView;
00139         matView.Translation(-m_CamPos.x, -m_CamPos.y, -m_CamPos.z);
00140         
00141         m_Camera = matView * CamRot;
00142         m_ViewProjection = m_Camera * m_Projection;
00143 
00144 }
00145 
00146 void CPipeline::PositionCamera(const Vector4 & Position, const float XRot, const float YRot)
00147 {
00148         m_CamPos = Position;
00149         m_YRot = YRot;
00150         m_XRot = XRot;
00151 }
00152 
00153 void CPipeline::PositionCamera(const Vector4 & Position, const Vector4 & LookAt)
00154 {
00155         // Calculate and set the camera matrix
00156         const Vector4 Up = Vector4(0.0f, 1.0f, 0.0f, 1.0f);
00157         m_Camera.LookAt(Position, LookAt, Up);
00158         
00159         // Set the position of the camera
00160         m_CamPos = Position;
00161         
00162         // Now we need to calculate the X and Y rotation variables.
00163         // First calculate the vector length along the xz plane
00164         float Hypot = Sqrt((Position.x - LookAt.x)*(Position.x - LookAt.x) 
00165                                                                    +(Position.z - LookAt.z)*(Position.z - LookAt.z));
00166         
00167         // If this vector is too small we are either looking directly up or down
00168         // Otherwise calculate the X rotation angle from the triangle.
00169         if(Hypot < 0.01f)
00170                 {
00171                 if((Position.y - LookAt.y) > 0.0f) 
00172                         m_XRot = -ROTXMAX;
00173                 else 
00174                         m_XRot = ROTXMAX;
00175                 }
00176         else
00177                 {
00178                 float Hypot2 = Sqrt((LookAt.y - Position.y)*(LookAt.y - Position.y) + Hypot * Hypot);
00179                 m_XRot = -ACos(Hypot/Hypot2);
00180                 }       
00181 
00182         // Now lets calculate the rotation round the Y axis
00183         // Get the vector along the xz plane
00184         Vector4 Lookxz, ZAxis = Vector4(0.0f, 0.0f, -1.0f, 1.0f);
00185         Lookxz.x =      LookAt.x - Position.x;
00186         Lookxz.y =      0.0f;
00187         Lookxz.z =      LookAt.z - Position.z;
00188         Lookxz.w = 1.0f;
00189         //ZAxis.x = 0.0f;
00190         //ZAxis.y = 0.0f;
00191         //ZAxis.z = -1.0f;
00192         //ZAxis.w = 1.0f;
00193         
00194         // Normalise the xz plane vector
00195         Lookxz.NormaliseSelf();
00196         
00197         // If this vector is too small we are looking directly up or down
00198         // so just set m_YRot to 0.0 and get out of here!
00199         // if(Lookxz.x == 0.0f && Lookxz.y == 0.0f && Lookxz.z == 0.0f && Lookxz.w == 0.0f)
00200         if(Lookxz.IsZeroVector())
00201                 {
00202                 m_YRot = 0.0f;
00203                 return;
00204                 }
00205         
00206         // Take the Dot product between the -ve z asix and the xz vector, this == cos(m_YRot)   
00207         float Dot = ZAxis.Dot3(Lookxz);
00208         
00209         // Get Y rotation and make sure the sign is correct.
00210         m_YRot = ACos(Dot);     
00211         if((LookAt.x - Position.x) > 0.0f)m_YRot = -m_YRot;
00212 }
00213         
00214 void CPipeline::SetLight1(const Vector4 & Direction, const Vector4 & Colour)
00215 {
00216         // Set the direction
00217         Vector4 Temp = Direction;
00218         assert(Temp.LengthSqr() > 0.0f);
00219         Temp.NormaliseSelf();
00220         m_LightDirs(0,0) = Temp.x;
00221         m_LightDirs(1,0) = Temp.y;
00222         m_LightDirs(2,0) = Temp.z;
00223 
00224         
00225         // Set the colour
00226         m_LightCols(0,0) = Colour.x;
00227         m_LightCols(0,1) = Colour.y;
00228         m_LightCols(0,2) = Colour.z;
00229 }
00230 
00231 void CPipeline::SetLight2(const Vector4 & Direction, const Vector4 & Colour)
00232 {
00233         // Set the direction
00234         Vector4 Temp = Direction;
00235         assert(Temp.LengthSqr() > 0.0f);
00236         Temp.NormaliseSelf();
00237         m_LightDirs(0,1) = Temp.x;
00238         m_LightDirs(1,1) = Temp.y;
00239         m_LightDirs(2,1) = Temp.z;
00240 
00241         
00242         // Set the colour
00243         m_LightCols(1,0) = Colour.x;
00244         m_LightCols(1,1) = Colour.y;
00245         m_LightCols(1,2) = Colour.z;
00246 }
00247 
00248 void CPipeline::SetLight3(const Vector4 & Direction, const Vector4 & Colour)
00249 {
00250         // Set the direction
00251         Vector4 Temp = Direction;
00252         assert(Temp.LengthSqr() > 0.0f);
00253         Temp.NormaliseSelf();
00254         m_LightDirs(0,2) = Temp.x;
00255         m_LightDirs(1,2) = Temp.y;
00256         m_LightDirs(2,2) = Temp.z;
00257 
00258         
00259         // Set the colour
00260         m_LightCols(2,0) = Colour.x;
00261         m_LightCols(2,1) = Colour.y;
00262         m_LightCols(2,2) = Colour.z;
00263 }
00264 
00265 void CPipeline::SetAmbient(const Vector4 & Colour)
00266 {
00267         // Set the colour
00268         m_LightCols(3,0) = Colour.x;
00269         m_LightCols(3,1) = Colour.y;
00270         m_LightCols(3,2) = Colour.z;
00271 
00272         //m_LightDirs.DumpMatrix4x4();
00273         //m_LightCols.DumpMatrix4x4();
00274 }

Generated on Sun May 18 21:45:08 2008 for PS2X by  doxygen 1.5.4