/* ##C_FILE# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ FILE : SHADDRAW.C DESCRIPTION : Main file for SHW Module VERSION : 1.02 / François Queinnec / Nintendo64 support 1.01 / Guenaele Mendroux / Level of detail 1.00 / Philippe Thiébaut / Creation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ #define SHW_MAIN /* FQ: This define forces shadows on every object*/ /* without checking for the custom bit..*/ /* usefull to determine wether it's the designer's fault */ /* or the programmer's one when there's no shadow.*/ /* #define SHW_FORCE_SHADOW 1*/ #define D_3dData_StructureDefine #define D_3dData_VariableDefine /* ##INCLUDE#---------------------------------------------------------------------------- Includes Files ---------------------------------------------------------------------------------------*/ #define D_3dData_StructureDefine #define D_3dData_VariableDefine #include "ACP_base.h" #include "GAM\ToolsCPA.h" #include "gam.h" #include "GEO.h" #include "GLI.h" #include "COL.h" #include "SPO.h" #include "LST.h" #include "MTH.h" #include "SND.h" #include "SCR.h" #include "SCT.h" /*This is the public section of SHW*/ #include "SHW\ShwCpa.h" /*Important: ALL GLOBAL MY CONSTANTS ARE HERE !!!*/ #include "SHW\ShwConst.h" #include "SHW\ShwStruc.h" #include "SHW\ShwMacro.h" #include "SHW\ShwHand.h" #include "SHW\ShwFunct.h" #include "SHW\ShwProto.h" /*This is the private section of SHW*/ #include "ShwPriv.h" #include "GLI\object.h" #if (!defined(U64)) #include "SNA.h" #endif #include "..\..\tempgrp\AI\AiGame\CAM_Base.h" #include "..\..\tempgrp\AI\AiGame\CAM_tool.h" #ifdef USE_IPT_DX5 #include "IPT_DX5.h" /* InPuT (absolutely before GAM.h)*/ #else /* USE_IPT_WIN */ #include "IPT.h" /* InPuT (absolutely before GAM.h)*/ #endif /* USE_IPT_WIN */ #include "PCS.h" /* Physical Collide Set */ #include "RND.h" /* RaNDom*/ #include "FIL.h" /* SeCTor*/ #ifndef D_THROW_PRT #include "PRT.h" #endif /* D_THROW_PRT */ #include "Mec.h" /*FQ*/ #ifdef U64 /* FQ SHADOW FIX*/ #include "mater_st.h" #include "objects.h" #include "sectinfo.h" #include "MainChar.h" #include "SPO\HieSpObj.h" #include "GMT\GmtStruc.h" /* XB 05/05/99 */ #include "GLI\Specif\u_load.h" /* End XB 05/05/99 */ #endif extern CPA_EXPORT unsigned long fn_ulStandardGameGetCustomBitsSO (HIE_tdxHandleToSuperObject hSupObj); extern unsigned long g_ulSpoMask; #include "PRF.h" /* ************************************************************************************/ /* ****************** Nintendo64 Specific Includes & Defines **************************/ /* ************************************************************************************/ #if defined(U64) #include "U_Elt.h" /* We include specific Nin64 Elements*/ #include "Element.h" /* We must include this to properly handle the object format conversion*/ #include "LDR\Specif\getval.h" #include "LDR\Specif\memload.h" #include "GLI\Specif\u_VMTLd.h" #include "h_bitmap.h" /* Here we declare the VTX and GFX Lists*/ Vtx *g_p_stVtxListForShadow[SHW_C_xNbMaxOfShadows]; Gfx *g_p_stGfxListForShadow[SHW_C_xNbMaxOfShadows]; MTH3D_tdstVector g_pstPickedPointArray[SHW_C_xNbMaxOfShadows]; extern unsigned short g_uwGlobalAlpha; /* The structure for the face-definitions*/ POS_tdstCompletePosition g_stTranslationMatrixForGoodScale[SHW_C_xNbMaxOfShadows]; #define SHW_C_xNbMaxOfGfxPerShadow 13 #define SHW_C_xU64ScaleForGeometricShadow 1000.0f #define SHW_C_xU64UVScaleForShadow 1024.0f #define SHW_C_xZeroForComparisonForN64 0.0001f #define SHW_C_xOneForComparisonForN64 0.9999f ACP_tdxHandleOfObject g_hShadowObjectN64[SHW_C_xNbMaxOfShadows]; int g_MustDisplayShadow; char g_UseNormalMatrixStack=0; /* This is the shift Z value for the shadow not to be */ /* exactly on the ground, but just a little higher...*/ /* To prevent ZBuffer problems....*/ /* #define SHW_C_ZBiasForZBuffer 0.08f*/ #define SHW_C_ZBiasForZBuffer 0.03f #define SHW_C_ucRedValue 50 #define SHW_C_ucGreenValue 50 #define SHW_C_ucBlueValue 50 #define SHW_C_ucAlphaValue 255 #endif /* U64 */ #if defined(USE_PROFILER) && !defined(PRESS_DEMO) extern void HIE_fn_vUpdateRasterForObject( GEO_tdstGeometricObject *p_stObject, unsigned long _ulRasterObject, unsigned long _ulRasterFace, unsigned long _ulRasterElement ); #else #define HIE_fn_vUpdateRasterForObject(p_stObject,_ulRasterObject,_ulRasterFace,_ulRasterElement) #endif /* USE_PROFILER */ /*****************************************************************/ /************************ Globalvariables ************************/ /*****************************************************************/ GLD_tdstDeviceAttributes g_stDevAttrib; ACP_tdxHandleOfMaterial g_hShadowPolygonVisualMaterial; GMT_tdxHandleToGameMaterial g_hShadowPolygonGameMaterial; GMT_tdxHandleToGameMaterial g_hShadowPolygonGameMaterialInit; short g_xIndexOfShadow; /*Array of geometric object that contains the shadow faces to be drawn*/ ACP_tdxHandleOfObject p_hHandleOfGeometricShadowObject[SHW_C_xNbMaxOfShadows]; ACP_tdxHandleOfElement g_p_hHandleOfElementForShadow[SHW_C_xNbMaxOfShadows]; #define NO_COMPLEX_SHADOW #define SHW_C_xMinZValueForShadowedFace MTH_M_xFloatToReal(0.5f) void SHW_fn_vSentToViewPort(struct GLD_tdstViewportAttributes_ *_p_stVpt, HIE_tdxHandleToSuperObject _hHandleOfCharacter, HIE_tdxHandleToSuperObject _hSprObjSector, long _lSectorDrawmask, ACP_tdxHandleOfObject _hHandleOfGeometricShadowObject); extern char g_cSinusEffectState; extern MTH3D_tdstVector stSinEffectAmp; #ifndef NO_COMPLEX_SHADOW #include "shaddraw.cxx" /* this file contains all functions to process complex shadows*/ #else #ifndef _FIRE_DEADCODE_U64_ /* Added by RUC 04/06/99 */ GLI_tdstTexture *g_p_stTextureOfTextureShadow; #endif /* _FIRE_DEADCODE_U64_ */ /* Added by RUC 04/06/99 */ #endif #ifdef U64 /*****************************************************************/ /************** Nintendo64 Specific Functions ********************/ /*****************************************************************/ /* ##F=================================================================================== NAME : SHW_fn_vCreateElementU64IndexedTriangles DESCRIPTION : Create the structure of the element U64IndexedTriangles WARNING: ONLY FOR SHW MODULE !!! ========================================================================================= CREATION : Philippe Thiébaut =======================================================================================*/ void SHW_fn_vCreateElementU64IndexedTriangles (ACP_tdxHandleOfObject hU64ObjectForShadow, unsigned long uiElement) { GEO_tdstElementU64IndexedTriangles *p_stLocalElement; hU64ObjectForShadow->d_xListOfElementsTypes[uiElement]=GEO_C_xElementU64IndexedTriangles; GEO_M_CPAMalloc(hU64ObjectForShadow->d_stListOfElements[uiElement], void * , sizeof (GEO_tdstElementU64IndexedTriangles), E_uwGEONotEnoughtMemory); p_stLocalElement = (GEO_tdstElementU64IndexedTriangles *) hU64ObjectForShadow->d_stListOfElements[uiElement]; p_stLocalElement->p_stVtxList=NULL; p_stLocalElement->p_stGfxList=NULL; p_stLocalElement->hMaterial=NULL; #if defined(_U64_GLI_BENCH_) p_stLocalElement->uwNbFaces = 0L; p_stLocalElement->uwSizeOfFacesInBytes = 0L; #endif /* _U64_GLI_BENCH_ */ } /* ##F=================================================================================== NAME : SHW_fn_vAddPointToVtxList DESCRIPTION : Add a geometric 3D Vector with UV in the indexed VtxList ========================================================================================= CREATION : Philippe Thiébaut =======================================================================================*/ /* ANTI-BUG*/ /* Sometimes, the PC version sends me some really weird coordinates*/ /* Then, we simply don't draw shadows !!!*/ /* if (((ft1>32760.0f) && (ft1<-32760.0f)) || ((ft2>32760.0f) && (ft2<-32760.0)) || ((ft3>32760.0) && (ft3<-32760.0))) { g_MustDisplayShadow=0; return; } */ /* ##F=================================================================================== NAME : SHW_fn_vAddAllFacesToGfxList DESCRIPTION : Add all faces of the shadow or the footstep in the indexed GfxList ========================================================================================= CREATION : Philippe Thiébaut =======================================================================================*/ /* ========================================================================================= NAME : SHW_ConvertPCtoN64GeometricObject DESCRIPTION : converts a PC geometric Object to a U64 Geometric object NOTE : It's only for shadows, with only 1 element (GEO_tdstElementIndexedTriangles -> GEO_tdstElementU64IndexedTriangles) ========================================================================================= CREATION : François Queinnec =======================================================================================*/ /*/////////////////////////*/ /* MEGA ANTI-BUG !!!*/ /*/////////////////////////*/ /* { long lExposant; #define MIN_VALUE_FOR_EXPOSANT 125 lExposant=(((*((long *)&(pvPoints->xX)))>>23)&0xFF); if (lExposantxY)))>>23)&0xFF); if (lExposantxZ)))>>23)&0xFF); if (lExposantd_stListOfPoints; lNbPoints=SHW_C_xNbMaxOfPointsPerShadow; for(i=0;ixX=-33000.0f; pvPoints->xY=-33000.0f; pvPoints->xZ=-33000.0f; } for(i=0;ihVisualMaterial=NULL; g_p_stShadowMaterial->hMechanicsMaterial=NULL; g_p_stShadowMaterial->hSoundMaterial=NULL; g_p_stShadowMaterial->hCollideMaterial=NULL; /* fbolefeysot - 01/10/98*/ /* remove init values in GMT{*/ /* g_p_stShadowMaterial->p_stInitialValues=NULL;//END fbolefeysot}*/ #ifdef SECTOR_IN_GMT g_p_stShadowMaterial->hSectorMaterial=NULL; #endif GLI_xCreateMaterial(&(g_p_stShadowMaterial->hVisualMaterial)); hVisualMaterial=g_p_stShadowMaterial->hVisualMaterial; hVisualMaterial->xMaterialType = 2047; #ifndef CONST_VMT hVisualMaterial->lSpecularExponent=5; #endif if (p_stFix->xShadowTextureId==D_BINSCR_InvalidId) M_PrintfN64(("p_stFix->xShadowTextureId==D_BINSCR_InvalidId\n")); g_p_stShadowMaterial->hVisualMaterial->p_stTexture = (struct GLI_tdstTexture_ *)fn_p_stLoadTexture(p_stFix->xShadowTextureId); g_p_stShadowMaterial->hVisualMaterial->ulGouraudColor=0; fn_vFreeRomTmp( (void *)p_stFix ); /* Oliv'*/ /* The material has been loaded, so now we can really initialize */ /* the shadow variables*/ g_hShadowPolygonVisualMaterial = g_p_stShadowMaterial->hVisualMaterial; g_hShadowPolygonGameMaterial=g_p_stShadowMaterial; p_hHandleGeoShwObj = p_hHandleOfGeometricShadowObject; p_hHandleOfElementForShadow = g_p_hHandleOfElementForShadow; for (i=0;ixZ, MTH_M_xMul(_xInvGlobalNormalxZ, MTH_M_xAdd( MTH_M_xMul(_p_stGlobalNormalOfPickedFace->xX, MTH_M_xSub(_xOffsetX,_p_stPickedPoint->xX)), MTH_M_xMul(_p_stGlobalNormalOfPickedFace->xY, MTH_M_xSub(_xOffsetY,_p_stPickedPoint->xY)) ) ) ) ); } /* ##F=================================================================================== NAME : SHW_fn_vDrawShadow DESCRIPTION : Draw a Fake Shadow for a Character ========================================================================================= CREATION : Philippe Thiébaut =======================================================================================*/ void SHW_fn_vDrawShadow ( struct GLD_tdstViewportAttributes_ *_p_stVpt, HIE_tdxHandleToSuperObject _hHandleOfCharacter, HIE_tdxHandleToSuperObject _hSprObjSector, long _lSectorDrawmask) { MTH3D_tdstVector stGlobalNormalOfPickedFace,stStartPicking,stVertexAB,stPickedPoint; GEO_tdxHandleToMatrix hGlobalMatrixOfCharacter; MTH_tdxReal xCoefAltitude; #ifndef U64 GEO_tdstElementIndexedTriangles *p_stIndexedTriangle; #endif MTH_tdxReal xScaleX; MTH_tdxReal xScaleY; ACP_tdxHandleOfObject hHandleOfGeometricShadowObject = NULL; HIE_tdxHandleToSuperObject hTest; /* PRF_fn_vStartChrono(PRF_C_ulGLI8, NULL);*/ #ifndef U64 /* if there is no material for the shadow, there is no shadow*/ if (fn_x3dDataGetShadowMaterialFromSO(_hHandleOfCharacter) == NULL) return; #endif /* if bad viewport or not active, no shadow*/ if( HIE_fn_SO_bIsSuperimposed(_hHandleOfCharacter) || !fn_bf1StandardGameGetIsActive(M_GetMSHandle(_hHandleOfCharacter,StandardGame)) ) return; /* If character uses ZFar transparency and is too far, no shadow. */ if( ( fn_ulStandardGameGetCustomBitsSO(_hHandleOfCharacter) & GAM_C_CustBitUsesTransparencyZone ) && ( GEO_xGetZFarTransparencyLevel() == MTH_C_ZERO ) ) return; #ifdef NO_COMPLEX_SHADOW /* if quality of shadow is 0, no shadow*/ /*XB ShadowQuality is always 2*/ #ifndef U64 if (fn_x3dDataGetShadowQualityFromSO(_hHandleOfCharacter) == 0) return; #endif /* U64 */ /*End XB*/ #else /* if quality of shadow is 0, no shadow*/ g_xLevelOfQualityOfShadows = fn_x3dDataGetShadowQualityFromSO(_hHandleOfCharacter); if (g_xLevelOfQualityOfShadows == 0) return; if (g_xGeneralLevelOfQualityOfShadowsv.tc[0]=0; pVtxList->v.tc[1]=0; pVtxList->v.flag=0; pVtxList->v.cn[0]=255; pVtxList->v.cn[1]=255; pVtxList->v.cn[2]=255; pVtxList->v.cn[3]=255; pVtxList++; pVtxList->v.tc[0]=SHW_C_xU64UVScaleForShadow*2; pVtxList->v.tc[1]=0; pVtxList->v.flag=0; pVtxList->v.cn[0]=255; pVtxList->v.cn[1]=255; pVtxList->v.cn[2]=255; pVtxList->v.cn[3]=255; pVtxList++; pVtxList->v.tc[0]=SHW_C_xU64UVScaleForShadow*2; pVtxList->v.tc[1]=SHW_C_xU64UVScaleForShadow*2; pVtxList->v.flag=0; pVtxList->v.cn[0]=255; pVtxList->v.cn[1]=255; pVtxList->v.cn[2]=255; pVtxList->v.cn[3]=255; pVtxList++; pVtxList->v.tc[0]=0; pVtxList->v.tc[1]=SHW_C_xU64UVScaleForShadow*2; pVtxList->v.flag=0; pVtxList->v.cn[0]=255; pVtxList->v.cn[1]=255; pVtxList->v.cn[2]=255; pVtxList->v.cn[3]=255; pVtxList=g_p_stVtxListForShadow[g_xIndexOfShadow]; gSPClearGeometryMode(pGfx++,G_CULL_BOTH); gSPVertex(pGfx++,OS_K0_TO_PHYSICAL(pVtxList),4,0); gDPPipeSync(pGfx++); gSP2Triangles(pGfx++,0,3,1,0,1,3,2,0); gSPEndDisplayList(pGfx++); } #endif if (g_xIndexOfShadow < SHW_C_xNbMaxOfShadows) { HIE_tdxHandleToSuperObject hCurrentPerso,hHandleOfFather; SECT_tdxHandleOfElementLstCharacter hCharacterList; SECT_tdxHandleOfElementLstCollisionInteraction hCollisionElement; SECT_tdxHandleOfElementLstActivityInteraction hInteractionElement; long i,j; BOOL bFound = FALSE; /* XB 05/05/99 */ /* BOOL bSectorLimit = FALSE; */ /* End XB 05/05/99 */ #ifndef NO_COMPLEX_SHADOW if (g_xLevelOfQualityOfShadows == 2) { SHW_fn_vDrawComplexShadow(_p_stVpt,_hHandleOfCharacter,_hSprObjSector,_lSectorDrawmask); return; } #endif hGlobalMatrixOfCharacter=HIE_fn_hGetSuperObjectGlobalMatrix(_hHandleOfCharacter); POS_fn_vGetTranslationVector(hGlobalMatrixOfCharacter, &stStartPicking ) ; hHandleOfGeometricShadowObject = p_hHandleOfGeometricShadowObject[g_xIndexOfShadow]; xScaleX = MTH_M_xAbs(fn_x3dDataGetShadowScaleXFromSO(_hHandleOfCharacter)); xScaleY = MTH_M_xAbs(fn_x3dDataGetShadowScaleYFromSO(_hHandleOfCharacter)); /* object detection starts 1.8m upper the actor*/ stStartPicking.xZ = MTH_M_xAdd(stStartPicking.xZ,MTH_M_xFloatToReal(1.8f)); /* object are detected 14.5 meters below the actor*/ MTH3D_M_vSetVectorElements(&stVertexAB,MTH_C_ZERO,MTH_C_ZERO,MTH_M_xFloatToReal(-14.5f)); /* begin with tests on a perso, so reset the mask to scan all objects:*/ g_ulSpoMask = 0; /* first, look if the perso is on a platform...*/ hHandleOfFather = HIE_fn_hGetSuperObjectFather(_hHandleOfCharacter); if (HIE_fn_ulGetSuperObjectType(hHandleOfFather) & HIE_C_ulActor) { /* The perso is on a platform...*/ /* so detect only on the platform and nowhere else !*/ if ( (fn_ulStandardGameGetCustomBitsSO(hHandleOfFather) & GAM_C_CustBitShadowOnMe) && /* actor accepts shadows*/ (fn_bf1StandardGameGetIsActive(M_GetMSHandle(hHandleOfFather,StandardGame))) ) /* active*/ { if (HIE_bIntersectSegmentWithFirstSuperObject(&stStartPicking,&stVertexAB,hHandleOfFather,&stPickedPoint,&stGlobalNormalOfPickedFace,&hTest)) { /* intersection found, check normal*/ bFound |= MTH_M_bGreater(stGlobalNormalOfPickedFace.xZ,SHW_C_xMinZValueForShadowedFace); } } } else { /* search in dynamic hierarchy of sector*/ SECT_M_ForEachCharListInSector(_hSprObjSector,hCharacterList,i) { hCurrentPerso = SECT_GetCharacterInList(hCharacterList); if (hCurrentPerso != _hHandleOfCharacter) { if ( (fn_ulStandardGameGetCustomBitsSO(hCurrentPerso) & GAM_C_CustBitShadowOnMe) && /* actor accepts shadows*/ (fn_bf1StandardGameGetIsActive(M_GetMSHandle(hCurrentPerso,StandardGame))) ) /* active*/ { if (HIE_bIntersectSegmentWithFirstSuperObject(&stStartPicking,&stVertexAB,hCurrentPerso,&stPickedPoint,&stGlobalNormalOfPickedFace,&hTest)) { /* intersection found, check normal*/ bFound |= MTH_M_bGreater(stGlobalNormalOfPickedFace.xZ,SHW_C_xMinZValueForShadowedFace); } } } } /* test on a sector, so set global mask to check SPO shadow flag :*/ g_ulSpoMask = HIE_C_Flag_ulNoShadowOnMe; /* search in static hierarchy of sector*/ if (HIE_bIntersectSegmentWithFirstSuperObject(&stStartPicking,&stVertexAB,_hSprObjSector,&stPickedPoint,&stGlobalNormalOfPickedFace,&hTest)) { bFound |= (MTH_M_bGreater(stGlobalNormalOfPickedFace.xZ,SHW_C_xMinZValueForShadowedFace)); } /* if (!bFound)*/ /* {*/ /* didn't find in first sector!!!*/ /* search in all active sectors for actors...*/ /* test on actors, so reset global mask*/ g_ulSpoMask = 0; SECT_M_ForEachActivityNodeInActivityInteractionList(_hSprObjSector,hInteractionElement,i) { MTH3D_tdstVector stMin, stMax; HIE_tdxHandleToSuperObject hSector; SECT_tdxHandleOfSectorObject hSectorObject; /* scan every collision sector*/ hSector = SECT_GetSectorInActivityList(hInteractionElement); hSectorObject = (SECT_tdxHandleOfSectorObject) HIE_fn_hGetSuperObjectObject(hSector); /* if the sector border is not in intersection with the segment, don't scan its characters*/ /* get the border box of the sector*/ SECT_fn_vGetMinPointInBorder(hSectorObject, &stMin); SECT_fn_vGetMaxPointInBorder(hSectorObject, &stMax); if (INT_fn_bDetectIntersectSegmentWithBox (&stStartPicking,&stVertexAB,&stMin,&stMax,NULL)) { /* ok, intersection with segment*/ SECT_M_ForEachCharListInSector(hSector,hCharacterList,j) { /* scan every character of the collision sector*/ hCurrentPerso = SECT_GetCharacterInList(hCharacterList); if ((fn_ulStandardGameGetCustomBitsSO(hCurrentPerso) & GAM_C_CustBitShadowOnMe) && /* accept shadow*/ (fn_bf1StandardGameGetIsActive(M_GetMSHandle(hCurrentPerso,StandardGame)))) /* active*/ { if( HIE_bIntersectSegmentWithFirstSuperObject(&stStartPicking,&stVertexAB,hCurrentPerso,&stPickedPoint,&stGlobalNormalOfPickedFace,&hTest) ) { /* intersection found, check normal*/ bFound |= MTH_M_bGreater(stGlobalNormalOfPickedFace.xZ,SHW_C_xMinZValueForShadowedFace); } } } } } /* and then in all collision sectors for decor*/ /* test on a sector, so set global mask to check SPO shadow flag :*/ g_ulSpoMask = HIE_C_Flag_ulNoShadowOnMe; SECT_M_ForEachCollisionNodeInCollisionInteractionList(_hSprObjSector,hCollisionElement,i) { HIE_tdxHandleToSuperObject hSector; hSector = SECT_GetSectorInCollisionList(hCollisionElement); if (HIE_bIntersectSegmentWithFirstSuperObject(&stStartPicking,&stVertexAB,hSector,&stPickedPoint,&stGlobalNormalOfPickedFace,&hTest)) { /* intersection found, check normal*/ bFound |= MTH_M_bGreater(stGlobalNormalOfPickedFace.xZ,SHW_C_xMinZValueForShadowedFace); } } } /* }*/ if (bFound && MTH_M_bGreater(stGlobalNormalOfPickedFace.xZ,SHW_C_xMinZValueForShadowedFace) ) { /*Temporary point of shadow*/ MTH3D_tdstVector stPointOfShadowRectangle; /*Vectors used for the orientation of the shadow*/ MTH3D_tdstVector stCharacterRotation; /*Vectors used to compute picked point * 2*/ MTH3D_tdstVector stDblPicked; #ifndef U64 /*UV of the points of the shadow*/ ACP_tdst2DUVValues stUV; /*Reals used to simplify the calcul of coordinates*/ MTH_tdxReal xAX,xAY,xBX; #endif MTH_tdxReal xBY; /*Real to simplify the next calcul*/ MTH_tdxReal xInvGlobalNormalxZ=MTH_M_xInv(stGlobalNormalOfPickedFace.xZ); POS_fn_vGetRotationMatrix(hGlobalMatrixOfCharacter ,&stCharacterRotation,&stPointOfShadowRectangle,&stPointOfShadowRectangle) ; #ifndef U64 /*Important: Rotation doesn't have to take in account the Z coef*/ stCharacterRotation.xZ=MTH_C_ZERO; /*If the orientation is only in Z*/ if ((MTH_M_bLess(MTH_M_xAbs(stCharacterRotation.xX),MTH_M_xFloatToReal(0.1f)))&& (MTH_M_bLess(MTH_M_xAbs(stCharacterRotation.xY),MTH_M_xFloatToReal(0.1f)))) { stCharacterRotation.xX=MTH_C_InvSqrt2; stCharacterRotation.xY=MTH_C_InvSqrt2; } MTH3D_M_vNormalizeVector(&stCharacterRotation,&stCharacterRotation); /*Formula for scale*/ xCoefAltitude=MTH_M_xInv(MTH_M_xAdd(MTH_C_ONE,MTH_M_xMul(MTH_M_xFloatToReal(0.3f),MTH_M_xSub(stStartPicking.xZ,stPickedPoint.xZ)))); xScaleX=MTH_M_xMul(xScaleX,xCoefAltitude); xScaleY=MTH_M_xMul(xScaleY,xCoefAltitude); xAX = MTH_M_xMul(xScaleX,stCharacterRotation.xX); xAY = MTH_M_xMul(xScaleY,stCharacterRotation.xX); xBX = MTH_M_xMul(xScaleX,stCharacterRotation.xY); xBY = MTH_M_xMul(xScaleY,stCharacterRotation.xY); if ( ( (g_cSinusEffectState == 1) && ((HIE_fn_lGetSuperObjectDrawMask(hTest) & GLI_C_lHasNotSinusEffect) == 0) ) || ( (g_cSinusEffectState == 2) && (HIE_fn_lGetSuperObjectDrawMask(hTest) & GLI_C_lHasNotSinusEffect) ) || (g_cSinusEffectState == 3) ) { /* sinus effect --> set shadow at the top of sinus*/ stPickedPoint.xZ = MTH_M_xAdd(stPickedPoint.xZ,MTH_M_xFloatToReal(stSinEffectAmp.xY)); /* if shadow higher than rayman, set shadow under rayman*/ /* 0.3 is distance between rayman and shadow when raymn walks*/ if (MTH_M_bLess(MTH_M_xSub(stStartPicking.xZ,stPickedPoint.xZ),MTH_M_xFloatToReal(0.3))) { stPickedPoint.xZ = MTH_M_xSub(stStartPicking.xZ,MTH_M_xFloatToReal(0.3f)); } } stPickedPoint.xZ = MTH_M_xAdd(stPickedPoint.xZ,MTH_M_xFloatToReal(0.03f)); /*First Point*/ stPointOfShadowRectangle.xX = MTH_M_xAdd(stPickedPoint.xX,MTH_M_xSub(xAX,xBY)); stPointOfShadowRectangle.xY = MTH_M_xAdd(stPickedPoint.xY,MTH_M_xAdd(xBX,xAY)); stPointOfShadowRectangle.xZ = SHW_fn_vComputeZofShadowPoint(&stPickedPoint,&stGlobalNormalOfPickedFace,xInvGlobalNormalxZ,stPointOfShadowRectangle.xX,stPointOfShadowRectangle.xY); #else /* U64 */ if (xScaleY>xScaleX) xScaleX=xScaleY; /* Since Shadows are always round */ /*Formula for scale*/ xCoefAltitude=MTH_M_xInv(MTH_M_xAdd(MTH_C_ONE,MTH_M_xMul(MTH_M_xFloatToReal(0.3f),MTH_M_xSub(stStartPicking.xZ,stPickedPoint.xZ)))); xScaleX=MTH_M_xMul(xScaleX,xCoefAltitude); /*xAX */ xBY = xScaleX*(MTH_C_InvSqrt2*2.0f); /* xBY = xAX+xAX; */ stPickedPoint.xZ = MTH_M_xAdd(stPickedPoint.xZ,MTH_M_xFloatToReal(0.03f)); /*First Point*/ stPointOfShadowRectangle.xX = stPickedPoint.xX; stPointOfShadowRectangle.xY = MTH_M_xAdd(stPickedPoint.xY,xBY); stPointOfShadowRectangle.xZ = SHW_fn_vComputeZofShadowPoint(&stPickedPoint,&stGlobalNormalOfPickedFace,xInvGlobalNormalxZ,stPointOfShadowRectangle.xX,stPointOfShadowRectangle.xY); #endif /* U64 */ /* Now we automatically create the N64 Geometric object so that we don't have to convert it in N64 format anymore =o) */ #ifndef U64 /* PC VERSION : Please inform Francois Queinnec when modifying this part of code ! */ GEO_vSetPointOfObject(hHandleOfGeometricShadowObject,&stPointOfShadowRectangle,0); stUV.xU=MTH_C_ZERO; stUV.xV=MTH_C_ZERO; GEO_vSetUVOfIndexedTriangles(hHandleOfGeometricShadowObject,0,0,&stUV); /*End of First Point*/ MTH3D_M_vMulScalarVector(&stDblPicked,MTH_M_xFloatToReal(2.0f),&stPickedPoint); /*Third Point*/ stPointOfShadowRectangle.xX = MTH_M_xSub(stDblPicked.xX,stPointOfShadowRectangle.xX); stPointOfShadowRectangle.xY = MTH_M_xSub(stDblPicked.xY,stPointOfShadowRectangle.xY); stPointOfShadowRectangle.xZ = MTH_M_xSub(stDblPicked.xZ,stPointOfShadowRectangle.xZ); GEO_vSetPointOfObject(hHandleOfGeometricShadowObject,&stPointOfShadowRectangle,2); stUV.xU=MTH_C_ONE; stUV.xV=MTH_C_ONE; GEO_vSetUVOfIndexedTriangles(hHandleOfGeometricShadowObject,0,2,&stUV); /*End of Third Point*/ /*Second Point*/ stPointOfShadowRectangle.xX = MTH_M_xAdd(stPickedPoint.xX,MTH_M_xAdd(xAX,xBY)); stPointOfShadowRectangle.xY = MTH_M_xAdd(stPickedPoint.xY,MTH_M_xSub(xBX,xAY)); stPointOfShadowRectangle.xZ = SHW_fn_vComputeZofShadowPoint(&stPickedPoint,&stGlobalNormalOfPickedFace,xInvGlobalNormalxZ,stPointOfShadowRectangle.xX,stPointOfShadowRectangle.xY); GEO_vSetPointOfObject(hHandleOfGeometricShadowObject,&stPointOfShadowRectangle,1); stUV.xU=MTH_C_ONE; stUV.xV=MTH_C_ZERO; GEO_vSetUVOfIndexedTriangles(hHandleOfGeometricShadowObject,0,1,&stUV); /*End of Second Point*/ /*Fourth Point*/ stPointOfShadowRectangle.xX = MTH_M_xSub(stDblPicked.xX,stPointOfShadowRectangle.xX); stPointOfShadowRectangle.xY = MTH_M_xSub(stDblPicked.xY,stPointOfShadowRectangle.xY); stPointOfShadowRectangle.xZ = MTH_M_xSub(stDblPicked.xZ,stPointOfShadowRectangle.xZ); GEO_vSetPointOfObject(hHandleOfGeometricShadowObject,&stPointOfShadowRectangle,3); stUV.xU=MTH_C_ZERO; stUV.xV=MTH_C_ONE; GEO_vSetUVOfIndexedTriangles(hHandleOfGeometricShadowObject,0,3,&stUV); /*End of Fourth Point*/ /*I create my two faces of my shadow*/ GEO_vSetFaceOfIndexedTriangles(hHandleOfGeometricShadowObject,0,0,0,3,1); GEO_vSetIndexedUVOfFaceOfIndexedTriangles(hHandleOfGeometricShadowObject,0,0,0,3,1); GEO_vSetFaceOfIndexedTriangles(hHandleOfGeometricShadowObject,0,1,1,3,2); GEO_vSetIndexedUVOfFaceOfIndexedTriangles(hHandleOfGeometricShadowObject,0,1,1,3,2); hHandleOfGeometricShadowObject->xNbPoints=4; p_stIndexedTriangle = (GEO_tdstElementIndexedTriangles *)hHandleOfGeometricShadowObject->d_stListOfElements[0]; p_stIndexedTriangle->xNbFaces=2; SHW_fn_vSentToViewPort(_p_stVpt,_hHandleOfCharacter,_hSprObjSector,_lSectorDrawmask,hHandleOfGeometricShadowObject); #else /* U64 Version : */ { GEO_tdstElementU64IndexedTriangles *pElem; Vtx *pVtxList; Gfx *pGfx; /* First, we create, if necessary, the geometric object */ if (g_hShadowObjectN64[g_xIndexOfShadow]==NULL) { GEO_vCreateGeometricObject(&g_hShadowObjectN64[g_xIndexOfShadow],0,1); SHW_fn_vCreateElementU64IndexedTriangles(g_hShadowObjectN64[g_xIndexOfShadow],0); ((GEO_tdstElementU64IndexedTriangles *)(g_hShadowObjectN64[g_xIndexOfShadow]->d_stListOfElements[0]))->hMaterial=(GMT_tdxHandleToGameMaterial)g_hShadowPolygonVisualMaterial; (g_hShadowObjectN64[g_xIndexOfShadow])->fScale=SHW_C_xU64ScaleForGeometricShadow; g_hShadowObjectN64[g_xIndexOfShadow]->uwSymType=0xFFFF; g_hShadowObjectN64[g_xIndexOfShadow]->uwRliFlag=0; g_hShadowObjectN64[g_xIndexOfShadow]->xNbPoints=4; pElem=((GEO_tdstElementU64IndexedTriangles **)(g_hShadowObjectN64[g_xIndexOfShadow]->d_stListOfElements))[0]; #if defined(_U64_GLI_BENCH_) pElem->uwNbFaces=2; pElem->uwSizeOfFacesInBytes=6; #endif pElem->ulNbVertices=2; pElem->p_stVtxList=g_p_stVtxListForShadow[g_xIndexOfShadow]; pElem->p_stGfxList=g_p_stGfxListForShadow[g_xIndexOfShadow]; } pElem=((GEO_tdstElementU64IndexedTriangles **)(g_hShadowObjectN64[g_xIndexOfShadow]->d_stListOfElements))[0]; pVtxList=g_p_stVtxListForShadow[g_xIndexOfShadow]; pGfx=g_p_stGfxListForShadow[g_xIndexOfShadow]; /* First Point */ pVtxList->v.ob[0]=(short)((stPointOfShadowRectangle.xX-stPickedPoint.xX)*SHW_C_xU64ScaleForGeometricShadow); pVtxList->v.ob[1]=(short)((stPointOfShadowRectangle.xY-stPickedPoint.xY)*SHW_C_xU64ScaleForGeometricShadow); pVtxList->v.ob[2]=(short)((stPointOfShadowRectangle.xZ-stPickedPoint.xZ+SHW_C_ZBiasForZBuffer)*SHW_C_xU64ScaleForGeometricShadow); /*End of First Point*/ /*Third Point*/ MTH3D_M_vMulScalarVector(&stDblPicked,MTH_M_xFloatToReal(2.0f),&stPickedPoint); stPointOfShadowRectangle.xX = MTH_M_xSub(stDblPicked.xX,stPointOfShadowRectangle.xX); stPointOfShadowRectangle.xY = MTH_M_xSub(stDblPicked.xY,stPointOfShadowRectangle.xY); stPointOfShadowRectangle.xZ = MTH_M_xSub(stDblPicked.xZ,stPointOfShadowRectangle.xZ); pVtxList+=2; pVtxList->v.ob[0]=(short)((stPointOfShadowRectangle.xX-stPickedPoint.xX)*SHW_C_xU64ScaleForGeometricShadow); pVtxList->v.ob[1]=(short)((stPointOfShadowRectangle.xY-stPickedPoint.xY)*SHW_C_xU64ScaleForGeometricShadow); pVtxList->v.ob[2]=(short)((stPointOfShadowRectangle.xZ-stPickedPoint.xZ+SHW_C_ZBiasForZBuffer)*SHW_C_xU64ScaleForGeometricShadow); /*End of Third Point*/ /*Second Point*/ stPointOfShadowRectangle.xX = MTH_M_xAdd(stPickedPoint.xX,xBY); stPointOfShadowRectangle.xY = stPickedPoint.xY; stPointOfShadowRectangle.xZ = SHW_fn_vComputeZofShadowPoint(&stPickedPoint,&stGlobalNormalOfPickedFace,xInvGlobalNormalxZ,stPointOfShadowRectangle.xX,stPointOfShadowRectangle.xY); pVtxList--; pVtxList->v.ob[0]=(short)((stPointOfShadowRectangle.xX-stPickedPoint.xX)*SHW_C_xU64ScaleForGeometricShadow); pVtxList->v.ob[1]=(short)((stPointOfShadowRectangle.xY-stPickedPoint.xY)*SHW_C_xU64ScaleForGeometricShadow); pVtxList->v.ob[2]=(short)((stPointOfShadowRectangle.xZ-stPickedPoint.xZ+SHW_C_ZBiasForZBuffer)*SHW_C_xU64ScaleForGeometricShadow); /*End of Second Point*/ /*Fourth Point*/ stPointOfShadowRectangle.xX = MTH_M_xSub(stDblPicked.xX,stPointOfShadowRectangle.xX); stPointOfShadowRectangle.xY = MTH_M_xSub(stDblPicked.xY,stPointOfShadowRectangle.xY); stPointOfShadowRectangle.xZ = MTH_M_xSub(stDblPicked.xZ,stPointOfShadowRectangle.xZ); pVtxList+=2; pVtxList->v.ob[0]=(short)((stPointOfShadowRectangle.xX-stPickedPoint.xX)*SHW_C_xU64ScaleForGeometricShadow); pVtxList->v.ob[1]=(short)((stPointOfShadowRectangle.xY-stPickedPoint.xY)*SHW_C_xU64ScaleForGeometricShadow); pVtxList->v.ob[2]=(short)((stPointOfShadowRectangle.xZ-stPickedPoint.xZ+SHW_C_ZBiasForZBuffer)*SHW_C_xU64ScaleForGeometricShadow); g_pstPickedPointArray[g_xIndexOfShadow].xX=stPickedPoint.xX; g_pstPickedPointArray[g_xIndexOfShadow].xY=stPickedPoint.xY; g_pstPickedPointArray[g_xIndexOfShadow].xZ=stPickedPoint.xZ; g_uwGlobalAlpha=255; SHW_fn_vSentToViewPort(_p_stVpt,_hHandleOfCharacter,_hSprObjSector,_lSectorDrawmask,g_hShadowObjectN64[g_xIndexOfShadow]); } #endif /* U64*/ g_xIndexOfShadow++; } } }