/* ======================================================================================= Name : Linear.c Description : compute serial operation on verticex ======================================================================================= */ /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ #define MTH_LOW /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ #include"gli_st.h" #include "GLI_Defn.h" #include "vertex.h" #include "light_st.h" #include "PvObj_st.h" #include "camera.h" /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ #ifdef __cplusplus extern "C" { #endif /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ /* ======================================================================================= Globals & Externals & Protos ======================================================================================= */ extern void GLI_vSinusEffetOn3DVertex( MTH3D_tdstVector * p_stVertex3D ); /* ======================================================================================= Macros ======================================================================================= */ #define GLI_M_SWAP(a,b)\ {\ fSwapValue = (a);\ (a) = (b);\ (b) = fSwapValue ;\ }\ /* ======================================================================================= Functions ======================================================================================= */ /* ---------------------------------------------------------------------------------------- Description : serial dot product : do a dot product for a list of source point source point are MTH3D_tdstVector (ie 3 float) ---------------------------------------------------------------------------------------- */ void GLI_xSerialDotProduct(long lNbOfVertex, MTH3D_tdstVector *p_stSource, float *p_stDest, MTH3D_tdstVector *p_stMultiplicator, long lIncrement) { float *p_stLastResult; p_stLastResult = p_stDest + lNbOfVertex; for ( ; p_stDest < p_stLastResult; p_stSource++ ) *p_stDest++ = MTH_M_xRealToFloat( MTH3D_M_xDotProductVector( p_stSource,p_stMultiplicator) ) ; } /* ---------------------------------------------------------------------------------------- Description : serial dot product : do a dot product for a list of point source point are Aligned3DVector (ie 4 float) ---------------------------------------------------------------------------------------- */ void GLI_xSerialDotProductAligned ( long lNbOfVertex, GLI_tdstAligned3DVector *p_stSource, float *p_stDest, MTH3D_tdstVector *p_stMultiplicator, long lIncrement) { float *p_stLastResult; p_stLastResult = p_stDest + lNbOfVertex; for ( ; p_stDest < p_stLastResult; p_stSource++ ) *p_stDest++ = MTH_M_xRealToFloat ( MTH3D_M_xDotProductVector( (MTH3D_tdstVector *)p_stSource, p_stMultiplicator) ) ; } /* ---------------------------------------------------------------------------------------- Description : multiply a list of vertex with a matrix source vertices are MTH3D_tdstVector (ie 3 float) target vertices are Aligned3DVector (ie 4 float) ---------------------------------------------------------------------------------------- */ void GLI_xSerialLinearOp( long lNbOfVertex, MTH3D_tdstVector *p_stSource, GLI_tdstAligned3DVector *p_stDest, POS_tdstCompletePosition *p_stMatrix) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ MTH3D_tdstVector stX,stY,stZ,stTrans; GLI_tdstAligned3DVector *p_stLastDest ; float fSwapValue; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ POS_fn_vGetTransformMatrix ( p_stMatrix,&stX,&stY,&stZ); GLI_M_SWAP (stX.xY,stY.xX); GLI_M_SWAP (stX.xZ,stZ.xX); GLI_M_SWAP (stY.xZ,stZ.xY); POS_fn_vGetTranslationVector( p_stMatrix,&stTrans); p_stLastDest = p_stDest + lNbOfVertex; for ( ; p_stDest < p_stLastDest; p_stDest++, p_stSource++) { p_stDest->xX = MTH3D_M_xDotProductVector ( &stX , p_stSource ) + stTrans.xX; p_stDest->xY = MTH3D_M_xDotProductVector ( &stY , p_stSource ) + stTrans.xY; p_stDest->xZ = MTH3D_M_xDotProductVector ( &stZ , p_stSource ) + stTrans.xZ; } } /* ---------------------------------------------------------------------------------------- Description : new version of above function, parameters are in big structure ---------------------------------------------------------------------------------------- */ void GLI_xNewSerialLinearOp ( GLI_tdstInternalGlobalValuesFor3dEngine *GLI_BG ) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLI_tdstAligned3DVector *p_stDest; GLI_tdstAligned3DVector *p_stLastDest; MTH3D_tdstVector *p_stSource ; float fSwapValue; MTH3D_tdstVector stX,stY,stZ,stTrans; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ POS_fn_vGetTransformMatrix ( &GLI_BG->gs_st_CurrentMatrixMultiplyedWithCameraMatrix, &stX, &stY, &stZ); GLI_M_SWAP (stX.xY,stY.xX); GLI_M_SWAP (stX.xZ,stZ.xX); GLI_M_SWAP (stY.xZ,stZ.xY); POS_fn_vGetTranslationVector( &GLI_BG->gs_st_CurrentMatrixMultiplyedWithCameraMatrix , &stTrans); p_stDest = GLI_BG->GLI_TurnedScaledDisplecedPoint; p_stSource = GLI_BG->p_stObj->d_stListOfPoints ; p_stLastDest = p_stDest + GLI_BG->p_stObj->xNbPoints; for ( ; p_stDest < p_stLastDest ; p_stDest++ , p_stSource++ ) { p_stDest->xX = MTH3D_M_xDotProductVector( &stX, p_stSource ) + stTrans.xX; p_stDest->xY = MTH3D_M_xDotProductVector( &stY, p_stSource ) + stTrans.xY; p_stDest->xZ = MTH3D_M_xDotProductVector( &stZ, p_stSource ) + stTrans.xZ; } } /* ---------------------------------------------------------------------------------------- Description : projection of 3D point that are in camera system axis ---------------------------------------------------------------------------------------- */ void GLI_xNewSerialProjOp ( GLI_tdstInternalGlobalValuesFor3dEngine *GLI_BG ) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLI_tdstAligned3DVector *p_stDest; GLI_tdstAligned3DVector *p_stLastDest; GLI_tdstAligned2DVector *p_st2DDest; float fScaleX,fScaleY; long lNewX; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ *(float * )&lNewX = 8000.0f; fScaleX = GLI_BG->p_stCurrentCamera->xScreen * GLI_BG->p_stCurrentCamera->stScale.xX ; fScaleY = GLI_BG->p_stCurrentCamera->xScreen * GLI_BG->p_stCurrentCamera->stScale.xY ; p_stDest = GLI_BG->GLI_TurnedScaledDisplecedPoint; p_st2DDest = GLI_BG->GLI_ScreenPoint; p_stLastDest = p_stDest + GLI_BG->p_stObj->xNbPoints; if (GLI_BG -> lClippingModeMask & GLI_C_ClipMaskZ) { for ( ; p_stDest < p_stLastDest ; p_stDest ++ , p_st2DDest++ ) { if ( *(long *)&p_stDest->xZ < *(long *)&GLI_BG->p_stCurrentCamera->xNear) { *(long *)&p_st2DDest -> xOoZ |= 0x80000000; *((unsigned long *)&p_st2DDest->xX) = lNewX | ((*((unsigned long *)&p_stDest->xX) & 0x80000000) ^ 0x80000000); *((unsigned long *)&p_st2DDest->xY) = lNewX | ((*((unsigned long *)&p_stDest->xY) & 0x80000000) ^ 0x80000000); continue ; } p_st2DDest->xOoZ = MTH_M_xInvLow(p_stDest->xZ ) ; p_st2DDest->xX = GLI_BG->p_stCurrentCamera->stTrans.xX + p_stDest->xX * fScaleX * p_st2DDest->xOoZ ; p_st2DDest->xY = GLI_BG->p_stCurrentCamera->stTrans.xY + p_stDest->xY * fScaleY * p_st2DDest->xOoZ ; p_st2DDest->xOoZ *= GLI_C_xZClippingNear; } } else { for ( ; p_stDest < p_stLastDest ; p_stDest ++ , p_st2DDest++ ) { p_st2DDest->xOoZ = MTH_M_xInvLow(p_stDest->xZ ) ; p_st2DDest->xX = GLI_BG->p_stCurrentCamera->stTrans.xX + p_stDest->xX * fScaleX * p_st2DDest->xOoZ ; p_st2DDest->xY = GLI_BG->p_stCurrentCamera->stTrans.xY + p_stDest->xY * fScaleY * p_st2DDest->xOoZ ; p_st2DDest->xOoZ *= GLI_C_xZClippingNear; } } } /* ---------------------------------------------------------------------------------------- Description : turned and project object vertex to get 2D coords ---------------------------------------------------------------------------------------- */ void GLI_xNewSerialLinearProjOpZClip ( GLI_tdstInternalGlobalValuesFor3dEngine *GLI_BG ) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLI_tdstAligned3DVector *p_stDest; GLI_tdstAligned3DVector *p_stLastDest; GLI_tdstAligned2DVector *p_st2DDest; MTH3D_tdstVector *p_stSource ; MTH3D_tdstVector stX, stY, stZ, stTrans; float fSwapValue, fScaleX, fScaleY, fTmpZ; long lNewX; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ *(float * )&lNewX = 8000.0f; fScaleX = GLI_BG->p_stCurrentCamera->xScreen * GLI_BG->p_stCurrentCamera->stScale.xX; fScaleY = GLI_BG->p_stCurrentCamera->xScreen * GLI_BG->p_stCurrentCamera->stScale.xY; POS_fn_vGetTransformMatrix ( &GLI_BG->gs_st_CurrentMatrixMultiplyedWithCameraMatrix, &stX, &stY, &stZ); GLI_M_SWAP (stX.xY,stY.xX); GLI_M_SWAP (stX.xZ,stZ.xX); GLI_M_SWAP (stY.xZ,stZ.xY); POS_fn_vGetTranslationVector( &GLI_BG -> gs_st_CurrentMatrixMultiplyedWithCameraMatrix , &stTrans); p_stDest = GLI_BG->GLI_TurnedScaledDisplecedPoint; p_st2DDest = GLI_BG->GLI_ScreenPoint; p_stSource = GLI_BG->p_stObj->d_stListOfPoints ; p_stLastDest = p_stDest + GLI_BG->p_stObj->xNbPoints; for ( ; p_stDest < p_stLastDest ; p_stDest ++ , p_stSource++ , p_st2DDest++ ) { p_stDest->xX = MTH3D_M_xDotProductVector( &stX , p_stSource ) + stTrans.xX; p_stDest->xY = MTH3D_M_xDotProductVector( &stY , p_stSource ) + stTrans.xY; p_stDest->xZ = MTH3D_M_xDotProductVector( &stZ , p_stSource ) + stTrans.xZ; if ( *(long *)&p_stDest->xZ < *(long *)&GLI_BG -> p_stCurrentCamera -> xNear) { /* point is before the near plane, so */ /* turn OoZ into negative value */ *(long *)&p_st2DDest -> xOoZ |= 0x80000000; /* and put X and Y to +/- 8000.0f according to the sign of the 3dPoint coordinates*/ *((unsigned long *)&p_st2DDest ->xX) = lNewX | ((*((unsigned long *)&p_stDest->xX) & 0x80000000) ^ 0x80000000); *((unsigned long *)&p_st2DDest ->xY) = lNewX | ((*((unsigned long *)&p_stDest->xY) & 0x80000000) ^ 0x80000000); continue ; } fTmpZ = MTH_M_xInvLow(p_stDest->xZ); p_st2DDest->xX = GLI_BG->p_stCurrentCamera->stTrans.xX + p_stDest->xX * fScaleX * fTmpZ; p_st2DDest->xY = GLI_BG->p_stCurrentCamera->stTrans.xY + p_stDest->xY * fScaleY * fTmpZ; p_st2DDest->xOoZ = fTmpZ * GLI_C_xZClippingNear; } } /* ---------------------------------------------------------------------------------------- Description : turned and project object vertex to get 2D coords apply sinus effect on 3D transformed vertices ---------------------------------------------------------------------------------------- */ void GLI_xSerialLinearProjOpZClipWithEffect ( GLI_tdstInternalGlobalValuesFor3dEngine *GLI_BG ) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLI_tdstAligned3DVector *p_stDest; GLI_tdstAligned3DVector *p_stLastDest; GLI_tdstAligned2DVector *p_st2DDest; MTH3D_tdstVector *p_stSource ; MTH3D_tdstVector stX,stY,stZ,stTrans; float fSwapValue,fScaleX,fScaleY, fTmpZ; long lNewX; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ *(float * )&lNewX = 8000.0f; fScaleX = GLI_BG->p_stCurrentCamera->xScreen * GLI_BG->p_stCurrentCamera->stScale.xX; fScaleY = GLI_BG->p_stCurrentCamera->xScreen * GLI_BG->p_stCurrentCamera->stScale.xY; POS_fn_vGetTransformMatrix ( &GLI_BG->gs_st_CurrentMatrixMultiplyedWithCameraMatrix, &stX, &stY, &stZ); GLI_M_SWAP (stX.xY,stY.xX); GLI_M_SWAP (stX.xZ,stZ.xX); GLI_M_SWAP (stY.xZ,stZ.xY); POS_fn_vGetTranslationVector( &GLI_BG -> gs_st_CurrentMatrixMultiplyedWithCameraMatrix , &stTrans); p_stDest = GLI_BG->GLI_TurnedScaledDisplecedPoint; p_st2DDest = GLI_BG->GLI_ScreenPoint; p_stSource = GLI_BG->p_stObj->d_stListOfPoints ; p_stLastDest = p_stDest + GLI_BG->p_stObj->xNbPoints; for ( ; p_stDest < p_stLastDest ; p_stDest ++ , p_stSource++ , p_st2DDest++ ) { p_stDest->xX = MTH3D_M_xDotProductVector( &stX , p_stSource ) + stTrans.xX; p_stDest->xY = MTH3D_M_xDotProductVector( &stY , p_stSource ) + stTrans.xY; p_stDest->xZ = MTH3D_M_xDotProductVector( &stZ , p_stSource ) + stTrans.xZ; GLI_vSinusEffetOn3DVertex((MTH3D_tdstVector *)p_stDest) ; if ( *(long *)&p_stDest->xZ < *(long *)&GLI_BG -> p_stCurrentCamera -> xNear) { *(long *)&p_st2DDest -> xOoZ |= 0x80000000; *((unsigned long *)&p_st2DDest ->xX) = lNewX | ((*((unsigned long *)&p_stDest->xX) & 0x80000000) ^ 0x80000000); *((unsigned long *)&p_st2DDest ->xY) = lNewX | ((*((unsigned long *)&p_stDest->xY) & 0x80000000) ^ 0x80000000); continue ; } fTmpZ = MTH_M_xInvLow(p_stDest->xZ); p_st2DDest->xX = GLI_BG->p_stCurrentCamera->stTrans.xX + p_stDest->xX * fScaleX * fTmpZ; p_st2DDest->xY = GLI_BG->p_stCurrentCamera->stTrans.xY + p_stDest->xY * fScaleY * fTmpZ; p_st2DDest->xOoZ = fTmpZ * GLI_C_xZClippingNear; } } /* ---------------------------------------------------------------------------------------- Description : turned and project object vertex to get 2D coords object is not Z clipped so do no test on Z ---------------------------------------------------------------------------------------- */ void GLI_xNewSerialLinearProjOpNoZClip ( GLI_tdstInternalGlobalValuesFor3dEngine *GLI_BG ) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLI_tdstAligned3DVector *p_stDest; GLI_tdstAligned3DVector *p_stLastDest; GLI_tdstAligned2DVector *p_st2DDest; MTH3D_tdstVector *p_stSource ; MTH3D_tdstVector stX, stY, stZ, stTrans; float fSwapValue, fScaleX, fScaleY, fTmpZ; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ fScaleX = GLI_BG->p_stCurrentCamera->xScreen * GLI_BG->p_stCurrentCamera->stScale.xX ; fScaleY = GLI_BG->p_stCurrentCamera->xScreen * GLI_BG->p_stCurrentCamera->stScale.xY ; POS_fn_vGetTransformMatrix ( &GLI_BG->gs_st_CurrentMatrixMultiplyedWithCameraMatrix , &stX , &stY , &stZ); GLI_M_SWAP (stX.xY,stY.xX); GLI_M_SWAP (stX.xZ,stZ.xX); GLI_M_SWAP (stY.xZ,stZ.xY); /* here, stX contains the first line of the matrix */ /* stY the second, and stz the third */ POS_fn_vGetTranslationVector( &GLI_BG->gs_st_CurrentMatrixMultiplyedWithCameraMatrix , &stTrans); p_stDest = GLI_BG->GLI_TurnedScaledDisplecedPoint; p_st2DDest = GLI_BG->GLI_ScreenPoint; p_stSource = GLI_BG->p_stObj->d_stListOfPoints ; p_stLastDest = p_stDest + GLI_BG->p_stObj->xNbPoints; for ( ; p_stDest < p_stLastDest ; p_stDest ++ , p_stSource++ , p_st2DDest++ ) { /* compute object's points in camera coordinates */ /* this is a faster version of the mullmatrixvertex*/ /* note that it uses the specially-computed stX, stY and stZ */ p_stDest->xZ = MTH3D_M_xDotProductVector( &stZ , p_stSource ) + stTrans.xZ; p_stDest->xX = MTH3D_M_xDotProductVector( &stX , p_stSource ) + stTrans.xX; p_stDest->xY = MTH3D_M_xDotProductVector( &stY , p_stSource ) + stTrans.xY; /* and scale the coordinates to let them fit in the viewport, with perspective correction */ fTmpZ = MTH_M_xInvLow(p_stDest->xZ); p_st2DDest->xX = GLI_BG->p_stCurrentCamera->stTrans.xX + p_stDest->xX * fScaleX * fTmpZ; p_st2DDest->xY = GLI_BG->p_stCurrentCamera->stTrans.xY + p_stDest->xY * fScaleY * fTmpZ; p_st2DDest->xOoZ = fTmpZ * GLI_C_xZClippingNear; } } /* ---------------------------------------------------------------------------------------- Description : turned and project object vertex to get 2D coords object is not Z clipped so do no test on Z apply sinus effect on transformed vertices ---------------------------------------------------------------------------------------- */ void GLI_xSerialLinearProjOpNoZClipWithEffect ( GLI_tdstInternalGlobalValuesFor3dEngine *GLI_BG ) { /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ GLI_tdstAligned3DVector *p_stDest; GLI_tdstAligned3DVector *p_stLastDest; GLI_tdstAligned2DVector *p_st2DDest; MTH3D_tdstVector *p_stSource ; MTH3D_tdstVector stX,stY,stZ,stTrans; float fSwapValue,fScaleX,fScaleY, fTmpZ; /*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/ fScaleX = GLI_BG->p_stCurrentCamera->xScreen * GLI_BG->p_stCurrentCamera->stScale.xX ; fScaleY = GLI_BG->p_stCurrentCamera->xScreen * GLI_BG->p_stCurrentCamera->stScale.xY ; POS_fn_vGetTransformMatrix ( &GLI_BG -> gs_st_CurrentMatrixMultiplyedWithCameraMatrix , &stX , &stY , &stZ); GLI_M_SWAP (stX.xY,stY.xX); GLI_M_SWAP (stX.xZ,stZ.xX); GLI_M_SWAP (stY.xZ,stZ.xY); POS_fn_vGetTranslationVector( &GLI_BG -> gs_st_CurrentMatrixMultiplyedWithCameraMatrix , &stTrans); p_stDest = GLI_BG->GLI_TurnedScaledDisplecedPoint; p_st2DDest = GLI_BG->GLI_ScreenPoint; p_stSource = GLI_BG->p_stObj->d_stListOfPoints ; p_stLastDest = p_stDest + GLI_BG -> p_stObj -> xNbPoints; for ( ; p_stDest < p_stLastDest ; p_stDest ++ , p_stSource++ , p_st2DDest++ ) { p_stDest->xZ = MTH3D_M_xDotProductVector ( &stZ , p_stSource ) + stTrans . xZ; p_stDest->xX = MTH3D_M_xDotProductVector ( &stX , p_stSource ) + stTrans . xX; p_stDest->xY = MTH3D_M_xDotProductVector ( &stY , p_stSource ) + stTrans . xY; GLI_vSinusEffetOn3DVertex((MTH3D_tdstVector *)p_stDest) ; fTmpZ = MTH_M_xInvLow(p_stDest->xZ); p_st2DDest -> xX = GLI_BG->p_stCurrentCamera->stTrans.xX + p_stDest -> xX * fScaleX * fTmpZ; p_st2DDest -> xY = GLI_BG->p_stCurrentCamera->stTrans.xY + p_stDest -> xY * fScaleY * fTmpZ; p_st2DDest -> xOoZ = fTmpZ * GLI_BG->p_stCurrentCamera->xNear ; } } #ifdef __cplusplus } /*extern "C"*/ #endif