00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include <math.h>
00023 #include <Assert.h>
00024 #include <Memory.h>
00025
00026 #include "Camera.h"
00027 #include "Ram.h"
00028 #include "ErrorLog.h"
00029
00030
00031 #include "DCommon.h"
00032
00033 typedef struct geCamera
00034 {
00035 geFloat Fov;
00036 geFloat Width;
00037 geFloat Height;
00038 geFloat Left,Right,Top,Bottom;
00039
00040 geFloat XRatio;
00041 geFloat YRatio;
00042 geFloat Scale;
00043 geFloat XCenter;
00044 geFloat YCenter;
00045
00046 geXForm3d XForm;
00047
00048 geBoolean UseVisPov;
00049 geXForm3d VisXForm;
00050 geXForm3d TransposeVisXForm;
00051 geVec3d VisPov;
00052
00053 geXForm3d TransposeXForm;
00054
00055 geVec3d Pov;
00056
00057 geFloat SinViewAngleX;
00058 geFloat CosViewAngleX;
00059 geFloat SinViewAngleY;
00060 geFloat CosViewAngleY;
00061
00062 geFloat ZScale;
00063
00064 geBoolean ZFarEnable;
00065 geFloat ZFar;
00066
00067 } geCamera;
00068
00069
00070 #ifndef max
00071 #define max(AA,BB) ( ((AA)>(BB)) ?(AA):(BB) )
00072 #endif
00073
00074 #define CAMERA_MINIMUM_PROJECTION_DISTANCE (0.010f)
00075
00076
00077
00078
00079 GENESISAPI geCamera *GENESISCC geCamera_Create(geFloat Fov, const geRect *Rect)
00080 {
00081 geCamera *Camera;
00082
00083 assert( Rect != NULL );
00084
00085 Camera = GE_RAM_ALLOCATE_STRUCT(geCamera);
00086 if (Camera == NULL)
00087 {
00088 geErrorLog_Add(-1, NULL);
00089 return NULL;
00090 }
00091
00092 memset(Camera, 0, sizeof(geCamera));
00093
00094 Camera->ZScale = 0.5f;
00095
00096 #if 0
00097 Camera->ZFar = 1000.0f;
00098 Camera->ZFarEnable = GE_TRUE;
00099 #endif
00100
00101 geCamera_SetAttributes(Camera,Fov,Rect);
00102 return Camera;
00103 }
00104
00105
00106
00107
00108 GENESISAPI void GENESISCC geCamera_Destroy(geCamera **pCamera)
00109 {
00110 assert( pCamera != NULL );
00111 assert( *pCamera != NULL );
00112 geRam_Free(*pCamera);
00113 *pCamera = NULL;
00114 }
00115
00116
00117
00118
00119 GENESISAPI void GENESISCC geCamera_SetZScale(geCamera *Camera, geFloat ZScale)
00120 {
00121 assert(Camera);
00122 Camera->ZScale = ZScale;
00123 }
00124
00125
00126
00127
00128 GENESISAPI geFloat GENESISCC geCamera_GetZScale(const geCamera *Camera)
00129 {
00130 assert(Camera);
00131 return Camera->ZScale;
00132 }
00133
00134
00135
00136
00137 GENESISAPI void GENESISCC geCamera_SetFarClipPlane(geCamera *Camera, geBoolean Enable, geFloat ZFar)
00138 {
00139 assert(Camera);
00140
00141 Camera->ZFarEnable = Enable;
00142 Camera->ZFar = ZFar;
00143 }
00144
00145
00146
00147
00148 GENESISAPI void GENESISCC geCamera_GetFarClipPlane(const geCamera *Camera, geBoolean *Enable, geFloat *ZFar)
00149 {
00150 assert(Camera);
00151
00152 *Enable = Camera->ZFarEnable;
00153 *ZFar = Camera->ZFar;
00154 }
00155
00156
00157
00158
00159 GENESISAPI void GENESISCC geCamera_GetClippingRect(const geCamera *Camera, geRect *Rect)
00160 {
00161 assert( Camera != NULL );
00162 assert( Rect != NULL );
00163 Rect->Left = (int32)Camera->Left;
00164 Rect->Right = (int32)Camera->Right;
00165 Rect->Top = (int32)Camera->Top;
00166 Rect->Bottom = (int32)Camera->Bottom;
00167 }
00168
00169
00170
00171
00172 void GENESISCC geCamera_GetWidthHeight(const geCamera *Camera,geFloat *Width,geFloat *Height)
00173 {
00174 assert( Width != NULL );
00175 assert( Height != NULL );
00176 assert( Camera != NULL );
00177
00178 *Width = Camera->Width;
00179 *Height = Camera->Height;
00180 }
00181
00182
00183
00184
00185 geFloat GENESISCC geCamera_GetScale(const geCamera *Camera)
00186 {
00187 assert( Camera != NULL );
00188
00189 return Camera->Scale;
00190 }
00191
00192
00193
00194
00195 GENESISAPI void GENESISCC geCamera_SetAttributes(geCamera *Camera, geFloat Fov, const geRect *Rect)
00196 {
00197
00198 #define TOO_SMALL (0.0001f) // width and Fov must be >= TOO_SMALL
00199
00200 geFloat Width, Height;
00201 geFloat OneOverFov;
00202
00203 assert (Camera != NULL);
00204 assert (Rect != NULL);
00205 assert (! ((Fov < TOO_SMALL) && (Fov > -TOO_SMALL)));
00206
00207 Width = (geFloat)(Rect->Right - Rect->Left)+1.0f;
00208 Height = (geFloat)(Rect->Bottom - Rect->Top)+1.0f;
00209
00210 assert( Width > 0.0f );
00211 assert( Height > 0.0f );
00212
00213 Camera->Width = Width;
00214 Camera->Height = Height;
00215
00216 Camera->Fov = Fov;
00217
00218 if ((Camera->Fov < TOO_SMALL) && (Camera->Fov > -TOO_SMALL))
00219 Camera->Fov = TOO_SMALL;
00220
00221 OneOverFov = 1.0f/Fov;
00222
00223 if (Width <=0.0f)
00224 Width = TOO_SMALL;
00225 if (Height <=0.0f)
00226 Height = TOO_SMALL;
00227
00228 Camera->XRatio = Width * OneOverFov;
00229 Camera->YRatio = Height * OneOverFov;
00230
00231 Camera->Scale = max(Camera->XRatio, Camera->YRatio);
00232
00233
00234 Camera->Left = (geFloat)Rect->Left;
00235 Camera->Right = (geFloat)Rect->Right;
00236 Camera->Top = (geFloat)Rect->Top;
00237 Camera->Bottom = (geFloat)Rect->Bottom;
00238
00239 Camera->XCenter = Camera->Left + ( Width * 0.5f ) - 0.5f;
00240 Camera->YCenter = Camera->Top + ( Height * 0.5f ) - 0.5f;
00241
00242 {
00243 geFloat Numerator = 2.0f * OneOverFov * Camera->Scale;
00244 double Angle;
00245 Angle = atan(Numerator / Camera->XRatio);
00246 Camera->CosViewAngleX = (geFloat)cos(Angle);
00247 Camera->SinViewAngleX = (geFloat)sin(Angle);
00248
00249 Angle = atan(Numerator / Camera->YRatio);
00250 Camera->CosViewAngleY = (geFloat)cos(Angle);
00251 Camera->SinViewAngleY = (geFloat)sin(Angle);
00252 }
00253 }
00254
00255
00256
00257
00258
00259 void geCamera_FillDriverInfo(geCamera *Camera)
00260 {
00261
00262
00263 #pragma message ("Camera.c : remove _FillDriverInfo, and thereby GlobalInfo!" )
00264 extern GInfo GlobalInfo;
00265 assert(Camera);
00266
00267 GlobalInfo.XScale =-Camera->Scale;
00268 GlobalInfo.YScale =-Camera->Scale;
00269 GlobalInfo.XScaleInv =1.0f / GlobalInfo.XScale;
00270 GlobalInfo.YScaleInv =1.0f / GlobalInfo.YScale;
00271 GlobalInfo.XCenter =Camera->XCenter;
00272 GlobalInfo.YCenter =Camera->YCenter;
00273
00274
00275 GlobalInfo.CXForm =Camera->XForm;
00276 GlobalInfo.Pov =Camera->Pov;
00277 GlobalInfo.ZScale =Camera->ZScale;
00278
00279 geXForm3d_Rotate(&Camera->XForm, &GlobalInfo.Pov, &GlobalInfo.CPov);
00280 }
00281
00282
00283
00284
00285 GENESISAPI void GENESISCC geCamera_ScreenPointToWorld ( const geCamera *Camera,
00286 int32 ScreenX,
00287 int32 ScreenY,
00288 geVec3d *Vector)
00289
00290
00291 {
00292 geVec3d In,Left,Up;
00293 geVec3d ScaledIn,ScaledLeft,ScaledUp ;
00294 geFloat XCenter ;
00295 geFloat YCenter ;
00296 geFloat Scale ;
00297 const geXForm3d *pM;
00298
00299 pM = &(Camera->TransposeXForm);
00300 XCenter = Camera->XCenter ;
00301 YCenter = Camera->YCenter ;
00302 Scale = Camera->Scale ;
00303
00304 geXForm3d_GetIn( pM, &In ) ;
00305 geXForm3d_GetLeft( pM, &Left ) ;
00306 geXForm3d_GetUp( pM, &Up ) ;
00307
00308 geVec3d_Scale(&In, Scale, &ScaledIn);
00309 geVec3d_Scale(&Left, XCenter - ((geFloat)ScreenX), &ScaledLeft );
00310 geVec3d_Scale(&Up, YCenter - ((geFloat)ScreenY), &ScaledUp );
00311
00312 geVec3d_Copy(&ScaledIn, Vector);
00313 geVec3d_Add(Vector, &ScaledLeft, Vector );
00314 geVec3d_Add(Vector, &ScaledUp, Vector );
00315 geVec3d_Normalize(Vector);
00316 }
00317
00318
00319
00320
00321
00322 GENESISAPI void GENESISCC geCamera_Project(const geCamera *Camera,
00323 const geVec3d *PointInCameraSpace,
00324 geVec3d *ProjectedPoint)
00325
00326
00327
00328 {
00329 geFloat ScaleOverZ;
00330 geFloat Z;
00331 assert( Camera != NULL );
00332 assert( PointInCameraSpace != NULL );
00333 assert( ProjectedPoint != NULL );
00334
00335 Z = -PointInCameraSpace->Z;
00336
00337 if (Z < CAMERA_MINIMUM_PROJECTION_DISTANCE)
00338 {
00339 Z = CAMERA_MINIMUM_PROJECTION_DISTANCE;
00340 }
00341
00342 ScaleOverZ = Camera->Scale / Z;
00343
00344 ProjectedPoint->Z = Z*Camera->ZScale;
00345
00346 ProjectedPoint->X = ( PointInCameraSpace->X * ScaleOverZ ) + Camera->XCenter;
00347
00348 ProjectedPoint->Y = Camera->YCenter - ( PointInCameraSpace->Y * ScaleOverZ );
00349 }
00350
00351
00352
00353
00354
00355 GENESISAPI void GENESISCC geCamera_ProjectZ(const geCamera *Camera,
00356 const geVec3d *PointInCameraSpace,
00357 geVec3d *ProjectedPoint)
00358
00359
00360
00361
00362 {
00363 geFloat OneOverZ;
00364 geFloat ScaleOverZ;
00365 geFloat Z;
00366 assert( Camera != NULL );
00367 assert( PointInCameraSpace != NULL );
00368 assert( ProjectedPoint != NULL );
00369
00370 Z = -PointInCameraSpace->Z;
00371
00372 if (Z < CAMERA_MINIMUM_PROJECTION_DISTANCE)
00373 {
00374 Z = CAMERA_MINIMUM_PROJECTION_DISTANCE;
00375 }
00376
00377 OneOverZ = 1.0f / Z;
00378 ScaleOverZ = Camera->Scale * (OneOverZ);
00379
00380 ProjectedPoint->Z = OneOverZ;
00381
00382 ProjectedPoint->X = ( PointInCameraSpace->X * ScaleOverZ ) + Camera->XCenter;
00383
00384 ProjectedPoint->Y = Camera->YCenter - ( PointInCameraSpace->Y * ScaleOverZ );
00385 }
00386
00387
00388
00389
00390
00391
00392
00393 void GENESISCC geCamera_ProjectAndClamp(const geCamera *Camera,
00394 const geVec3d *PointInCameraSpace,
00395 geVec3d *ProjectedPoint)
00396
00397
00398
00399
00400 {
00401 geFloat ScaleOverZ;
00402 geFloat X,Y,Z;
00403 assert( Camera != NULL );
00404 assert( PointInCameraSpace != NULL );
00405 assert( ProjectedPoint != NULL );
00406
00407 Z = -PointInCameraSpace->Z;
00408
00409 if (Z < CAMERA_MINIMUM_PROJECTION_DISTANCE)
00410 {
00411 Z = CAMERA_MINIMUM_PROJECTION_DISTANCE;
00412 }
00413
00414 ScaleOverZ = Camera->Scale / Z;
00415
00416 ProjectedPoint->Z = Z*Camera->ZScale;
00417
00418 X = ( PointInCameraSpace->X * ScaleOverZ ) + Camera->XCenter;
00419
00420 if (X < Camera->Left)
00421 X = Camera->Left;
00422 else if (X > Camera->Right)
00423 X = Camera->Right;
00424
00425 ProjectedPoint->X = X;
00426
00427 Y = Camera->YCenter - ( PointInCameraSpace->Y * ScaleOverZ );
00428
00429 if (Y < Camera->Top)
00430 Y = Camera->Top;
00431 else if (Y > Camera->Bottom)
00432 Y = Camera->Bottom;
00433
00434 ProjectedPoint->Y = Y;
00435 }
00436
00437
00438
00439
00440
00441 void GENESISCC geCamera_GetViewAngleXSinCos( const geCamera *Camera, geFloat *SinAngle, geFloat *CosAngle )
00442 {
00443 assert( Camera != NULL );
00444 assert( SinAngle );
00445 assert( CosAngle );
00446 *SinAngle = Camera->SinViewAngleX;
00447 *CosAngle = Camera->CosViewAngleX;
00448 }
00449
00450
00451
00452
00453 void GENESISCC geCamera_GetViewAngleYSinCos( const geCamera *Camera, geFloat *SinAngle, geFloat *CosAngle )
00454 {
00455 assert( Camera != NULL );
00456 assert( SinAngle );
00457 assert( CosAngle );
00458 *SinAngle = Camera->SinViewAngleY;
00459 *CosAngle = Camera->CosViewAngleY;
00460 }
00461
00462
00463
00464
00465 GENESISAPI void GENESISCC geCamera_Transform(const geCamera *Camera,
00466 const geVec3d *WorldSpacePoint,
00467 geVec3d *CameraSpacePoint)
00468 {
00469 assert( Camera );
00470 assert( WorldSpacePoint );
00471 assert( CameraSpacePoint );
00472
00473
00474 geXForm3d_Transform(&(Camera->XForm),WorldSpacePoint,CameraSpacePoint);
00475 }
00476
00477
00478
00479
00480
00481 GENESISAPI void GENESISCC geCamera_TransformArray(const geCamera *Camera,
00482 const geVec3d *WorldSpacePointPtr,
00483 geVec3d *CameraSpacePointPtr, int count)
00484 {
00485 assert( Camera );
00486 assert( WorldSpacePointPtr );
00487 assert( CameraSpacePointPtr );
00488
00489 while(count--)
00490 {
00491 geXForm3d_Transform(&(Camera->XForm),WorldSpacePointPtr++,CameraSpacePointPtr++);
00492 }
00493 }
00494
00495
00496
00497
00498 GENESISAPI void GENESISCC geCamera_TransformAndProjectArray(const geCamera *Camera,
00499 const geVec3d *WorldSpacePointPtr,
00500 geVec3d *ProjectedSpacePointPtr,
00501 int count)
00502 {
00503 assert( Camera );
00504 assert( WorldSpacePointPtr );
00505 assert( ProjectedSpacePointPtr );
00506 while(count--)
00507 {
00508 geCamera_TransformAndProject(Camera,WorldSpacePointPtr++,ProjectedSpacePointPtr++);
00509 }
00510 }
00511
00512
00513
00514
00515 GENESISAPI void GENESISCC geCamera_TransformAndProjectLArray(const geCamera *Camera,
00516 const GE_LVertex *WorldSpacePointPtr,
00517 GE_TLVertex *ProjectedSpacePointPtr, int count)
00518 {
00519 assert( Camera );
00520 assert( WorldSpacePointPtr );
00521 assert( ProjectedSpacePointPtr );
00522 while(count--)
00523 {
00524 geCamera_TransformAndProjectL(Camera,WorldSpacePointPtr++,ProjectedSpacePointPtr++);
00525 }
00526 }
00527
00528
00529
00530
00531 GENESISAPI void GENESISCC geCamera_TransformAndProject(const geCamera *Camera,
00532 const geVec3d *Point,
00533 geVec3d *ProjectedPoint)
00534
00535
00536
00537 {
00538 geFloat Z;
00539
00540 assert( Camera );
00541 assert( Point );
00542 assert( ProjectedPoint );
00543
00544 geXForm3d_Transform(&(Camera->XForm),Point,ProjectedPoint);
00545
00546 Z = - ProjectedPoint->Z;
00547
00548 Z = max(Z,CAMERA_MINIMUM_PROJECTION_DISTANCE);
00549
00550 ProjectedPoint->Z = Z*Camera->ZScale;
00551
00552 Z = Camera->Scale / Z;
00553
00554 ProjectedPoint->X = ( ProjectedPoint->X * Z ) + Camera->XCenter;
00555 ProjectedPoint->Y = - ( ProjectedPoint->Y * Z ) + Camera->YCenter;
00556 }
00557
00558
00559
00560
00561
00562 GENESISAPI void GENESISCC geCamera_TransformAndProjectL(const geCamera *Camera,
00563 const GE_LVertex *Point,
00564 GE_TLVertex *ProjectedPoint)
00565
00566
00567
00568 {
00569 geFloat ScaleOverZ;
00570 geFloat Z;
00571
00572 assert( Camera );
00573 assert( Point );
00574 assert( ProjectedPoint );
00575
00576 geXForm3d_Transform(&(Camera->XForm),(geVec3d *)Point,(geVec3d *)ProjectedPoint);
00577
00578 Z = - ProjectedPoint->z;
00579
00580 Z = max(Z,CAMERA_MINIMUM_PROJECTION_DISTANCE);
00581
00582 ScaleOverZ = Camera->Scale / Z;
00583
00584 ProjectedPoint->z = Z*Camera->ZScale;
00585 ProjectedPoint->x = ( ProjectedPoint->x * ScaleOverZ ) + Camera->XCenter;
00586 ProjectedPoint->y = - ( ProjectedPoint->y * ScaleOverZ ) + Camera->YCenter;
00587
00588 ProjectedPoint->u = Point->u;
00589 ProjectedPoint->v = Point->v;
00590 ProjectedPoint->r = Point->r;
00591 ProjectedPoint->g = Point->g;
00592 ProjectedPoint->b = Point->b;
00593 ProjectedPoint->a = Point->a;
00594 }
00595
00596
00597
00598
00599 GENESISAPI geBoolean GENESISCC geCamera_SetWorldSpaceXForm(geCamera *Camera, const geXForm3d *XForm)
00600 {
00601 assert(Camera != NULL);
00602 assert(XForm != NULL);
00603
00604 Camera->TransposeXForm = *XForm;
00605
00606
00607
00608 geXForm3d_GetTranspose(XForm, &Camera->XForm);
00609
00610 Camera->Pov = XForm->Translation;
00611
00612 return GE_TRUE;
00613 }
00614
00615
00616
00617
00618 GENESISAPI geBoolean GENESISCC geCamera_SetWorldSpaceVisXForm(geCamera *Camera, const geXForm3d *XForm)
00619 {
00620 assert(Camera != NULL);
00621
00622 if (XForm)
00623 {
00624 Camera->TransposeVisXForm = *XForm;
00625 Camera->VisPov = XForm->Translation;
00626 geXForm3d_GetTranspose(XForm, &Camera->VisXForm);
00627
00628 Camera->UseVisPov = GE_TRUE;
00629 }
00630 else
00631 {
00632 Camera->UseVisPov = GE_FALSE;
00633 }
00634
00635 return GE_TRUE;
00636 }
00637
00638
00639
00640
00641
00642 GENESISAPI const geXForm3d * GENESISCC geCamera_GetWorldSpaceXForm( const geCamera *Camera)
00643 {
00644 assert(Camera );
00645 return &(Camera->TransposeXForm);
00646 }
00647
00648
00649
00650
00651 GENESISAPI const geXForm3d * GENESISCC geCamera_GetCameraSpaceXForm( const geCamera *Camera)
00652 {
00653 assert(Camera != NULL);
00654 return &(Camera->XForm);
00655 }
00656
00657
00658
00659
00660 GENESISAPI const geXForm3d * GENESISCC geCamera_GetCameraSpaceVisXForm( const geCamera *Camera)
00661 {
00662 assert(Camera != NULL);
00663
00664 if (Camera->UseVisPov)
00665 return &(Camera->VisXForm);
00666 else
00667 return &(Camera->XForm);
00668 }
00669
00670
00671
00672
00673 GENESISAPI const geXForm3d * GENESISCC geCamera_GetWorldSpaceVisXForm( const geCamera *Camera)
00674 {
00675 assert(Camera != NULL);
00676
00677 if (Camera->UseVisPov)
00678 return &(Camera->TransposeVisXForm);
00679 else
00680 return &(Camera->TransposeXForm);
00681 }
00682
00683
00684
00685
00686 const geVec3d *GENESISCC geCamera_GetPov(const geCamera *Camera)
00687 {
00688 assert( Camera != NULL );
00689 return &(Camera->Pov);
00690 }
00691
00692
00693
00694
00695 const geVec3d *GENESISCC geCamera_GetVisPov(const geCamera *Camera)
00696 {
00697 assert( Camera != NULL );
00698
00699 if (Camera->UseVisPov)
00700 return &(Camera->VisPov);
00701 else
00702 return &(Camera->Pov);
00703 }
00704
00705
00706
00707
00708
00709 GENESISAPI geBoolean GENESISCC geCamera_ConvertWorldSpaceToCameraSpace(const geXForm3d *WXForm, geXForm3d *CXForm)
00710 {
00711
00712 CXForm->AX = WXForm->AX;
00713 CXForm->AY = WXForm->BX;
00714 CXForm->AZ = WXForm->CX;
00715
00716 CXForm->BX = WXForm->AY;
00717 CXForm->BY = WXForm->BY;
00718 CXForm->BZ = WXForm->CY;
00719
00720 CXForm->CX = WXForm->AZ;
00721 CXForm->CY = WXForm->BZ;
00722 CXForm->CZ = WXForm->CZ;
00723
00724 CXForm->Translation = WXForm->Translation;
00725
00726 geVec3d_Inverse(&CXForm->Translation);
00727
00728
00729 geXForm3d_Rotate(CXForm, &CXForm->Translation, &CXForm->Translation);
00730
00731 return GE_TRUE;
00732 }