// Create render model structure for rendering an attached model BOOL CModelObject::CreateAttachment( CRenderModel &rmMain, CAttachmentModelObject &amo) { _pfModelProfile.StartTimer( CModelProfile::PTI_CREATEATTACHMENT); _pfModelProfile.IncrementTimerAveragingCounter( CModelProfile::PTI_CREATEATTACHMENT); CRenderModel &rmAttached = *amo.amo_prm; rmAttached.rm_ulFlags = rmMain.rm_ulFlags&(RMF_FOG|RMF_HAZE|RMF_WEAPON) | RMF_ATTACHMENT; // get the position rmMain.rm_pmdModelData->md_aampAttachedPosition.Lock(); const CAttachedModelPosition & = rmMain.rm_pmdModelData->md_aampAttachedPosition[amo.amo_iAttachedPosition]; rmMain.rm_pmdModelData->md_aampAttachedPosition.Unlock(); // copy common values rmAttached.rm_vLightDirection = rmMain.rm_vLightDirection; rmAttached.rm_fDistanceFactor = rmMain.rm_fDistanceFactor; rmAttached.rm_colLight = rmMain.rm_colLight; rmAttached.rm_colAmbient = rmMain.rm_colAmbient; rmAttached.rm_colBlend = rmMain.rm_colBlend; // unpack the reference vertices FLOAT3D vCenter, vFront, vUp; const INDEX iCenter = amp.amp_iCenterVertex; const INDEX iFront = amp.amp_iFrontVertex; const INDEX iUp = amp.amp_iUpVertex; UnpackVertex( rmMain, iCenter, vCenter); UnpackVertex( rmMain, iFront, vFront); UnpackVertex( rmMain, iUp, vUp); // create front and up direction vectors FLOAT3D vY = vUp - vCenter; FLOAT3D vZ = vCenter - vFront; // project center and directions from object to absolute space const FLOATmatrix3D &mO2A = rmMain.rm_mObjectRotation; const FLOAT3D &vO2A = rmMain.rm_vObjectPosition; vCenter = vCenter*mO2A +vO2A; vY = vY *mO2A; vZ = vZ *mO2A; // make a rotation matrix from the direction vectors FLOAT3D vX = vY*vZ; vY = vZ*vX; vX.Normalize(); vY.Normalize(); vZ.Normalize(); FLOATmatrix3D mOrientation; mOrientation(1,1) = vX(1); mOrientation(1,2) = vY(1); mOrientation(1,3) = vZ(1); mOrientation(2,1) = vX(2); mOrientation(2,2) = vY(2); mOrientation(2,3) = vZ(2); mOrientation(3,1) = vX(3); mOrientation(3,2) = vY(3); mOrientation(3,3) = vZ(3); // adjust for relative placement of the attachment FLOAT3D vOffset; FLOATmatrix3D mRelative; MakeRotationMatrixFast( mRelative, amo.amo_plRelative.pl_OrientationAngle); vOffset(1) = amo.amo_plRelative.pl_PositionVector(1) * mo_Stretch(1); vOffset(2) = amo.amo_plRelative.pl_PositionVector(2) * mo_Stretch(2); vOffset(3) = amo.amo_plRelative.pl_PositionVector(3) * mo_Stretch(3); FLOAT3D vO = vCenter + vOffset * mOrientation; mOrientation *= mRelative; // convert absolute to relative orientation rmAttached.SetObjectPlacement( vO, mOrientation); // done here if clipping optimizations are not allowed extern INDEX gap_iOptimizeClipping; if( gap_iOptimizeClipping<1) { gap_iOptimizeClipping = 0; _pfModelProfile.StopTimer( CModelProfile::PTI_CREATEATTACHMENT); return TRUE; } // test attachment to frustum and/or mirror FLOAT3D vHandle; _aprProjection->PreClip( vO, vHandle); CalculateBoundingBox( &amo.amo_moModelObject, rmAttached); // compose view-space bounding box and sphere of an attacment const FLOAT fR = Max( rmAttached.rm_vObjectMinBB.Length(), rmAttached.rm_vObjectMaxBB.Length()); const FLOATobbox3D boxEntity( FLOATaabbox3D(rmAttached.rm_vObjectMinBB, rmAttached.rm_vObjectMaxBB), vHandle, _aprProjection->pr_ViewerRotationMatrix*mOrientation); // frustum test? if( gap_iOptimizeClipping>1) { // test sphere against frustrum INDEX iFrustumTest = _aprProjection->TestSphereToFrustum(vHandle,fR); if( iFrustumTest==0) { // test box if sphere cut one of frustum planes iFrustumTest = _aprProjection->TestBoxToFrustum(boxEntity); } // mark if attachment is fully inside frustum if( iFrustumTest>0) rmAttached.rm_ulFlags |= RMF_INSIDE; else if( iFrustumTest<0) { // if completely outside of frustum // signal skip rendering only if doesn't have any attachments _pfModelProfile.StopTimer( CModelProfile::PTI_CREATEATTACHMENT); return !amo.amo_moModelObject.mo_lhAttachments.IsEmpty(); } } // test sphere against mirror/warp plane (if any) if( _aprProjection->pr_bMirror || _aprProjection->pr_bWarp) { INDEX iMirrorPlaneTest; const FLOAT fPlaneDistance = _aprProjection->pr_plMirrorView.PointDistance(vHandle); if( fPlaneDistance < -fR) iMirrorPlaneTest = -1; else if( fPlaneDistance > +fR) iMirrorPlaneTest = +1; else { // test box if sphere cut mirror plane iMirrorPlaneTest = boxEntity.TestAgainstPlane(_aprProjection->pr_plMirrorView); } // mark if attachment is fully inside mirror if( iMirrorPlaneTest>0) rmAttached.rm_ulFlags |= RMF_INMIRROR; else if( iMirrorPlaneTest<0) { // if completely outside mirror // signal skip rendering only if doesn't have any attachments _pfModelProfile.StopTimer( CModelProfile::PTI_CREATEATTACHMENT); return !amo.amo_moModelObject.mo_lhAttachments.IsEmpty(); } } // all done _pfModelProfile.StopTimer( CModelProfile::PTI_CREATEATTACHMENT); return TRUE; }
int ReadMesh(char** buf, int frmcount, float scale, uint32 flags) { if(!*buf) return 1; MEMesh2 *mesh=(MEMesh2*)*buf; MEMD2_VERTEX *vb; if(!scale) scale=1.0f; *buf+=sizeof(MEMesh2); if(!mesh->vcount || !mesh->icount) return 1; mesh->Scale.x=65525.0f/mesh->Scale.x; mesh->Scale.y=65525.0f/mesh->Scale.y; mesh->Scale.z=65525.0f/mesh->Scale.z; mesh->UVScale.x=65525.0f/mesh->UVScale.x; mesh->UVScale.y=65525.0f/mesh->UVScale.y; F3DSubObject &sub = pModel->GetMeshChunk()->subObjects.push(); MFString_Copy(sub.name, mesh->Name); sub.matSubobjects[0].materialIndex = mesh->MaterialID; // read vertex data for(int a=0; a<frmcount; a++) { vb=(MEMD2_VERTEX*)*buf; if(a == 0) // only first frame for now... { for(int b=0; b<mesh->vcount; b++) { UnpackVertex(&vb[b], mesh, scale, sub); } } *buf+=sizeof(MEMD2_VERTEX)*mesh->vcount; } // read triangles MFDebug_Assert(mesh->icount % 3 == 0, "Incorrect number of indices..."); F3DMaterialSubobject &msub = sub.matSubobjects[0]; uint16 *pI = (uint16*)*buf; int tris =0; int v = 0; for(int a=0; a<mesh->icount; a++) { msub.triangles[tris].v[v] = pI[a]; ++v; if(v>=3) { v = 0; ++tris; } } *buf+=sizeof(unsigned short)*mesh->icount; return 0; }