RwMatrix carfx_view, carfx_env1Inv, carfx_env2Inv; RwV3d carfx_lightdir; // view space RwFrame *carfx_env1Frame, *carfx_env2Frame; RxPipeline *CCustomCVCarEnvMapPipeline::MatPipe; RxPipeline *CCustomCVCarEnvMapUV2Pipeline::MatPipe; RwV3d axis_X = { 1.0, 0.0, 0.0 }; RwV3d axis_Y = { 0.0, 1.0, 0.0 }; RwV3d axis_Z = { 0.0, 0.0, 1.0 }; void CCustomCVCarEnvMapPipeline::CreatePipe(void) { CCustomCVCarEnvMapPipeline::CreateMatPipes(...); /* --- register pipes --- ... */ if(carfx_env1Frame == NULL){ carfx_env1Frame = RwFrameCreate(); RwMatrixRotate(RwFrameGetMatrix(carfx_env1Frame), &axis_X, 33.0, rwCOMBINEREPLACE); RwMatrixRotate(RwFrameGetMatrix(carfx_env1Frame), &axis_Y, -33.0, rwCOMBINEPOSTCONCAT); RwMatrixRotate(RwFrameGetMatrix(carfx_env1Frame), &axis_Z, 50.0, rwCOMBINEPOSTCONCAT); RwFrameUpdateObjects(carfx_env1Frame); RwFrameGetLTM(carfx_env1Frame); } if(carfx_env2Frame == NULL){ carfx_env2Frame = RwFrameCreate(); RwFrameSetIdentity(carfx_env2Frame); RwFrameUpdateObjects(carfx_env2Frame); } /* --- ... */ } void CCustomCVCarEnvMapPipeline::PreRenderUpdate(void) { RwV3d l; RwMatrixInvert(&carfx_view, RwFrameGetLTM(RwCameraGetFrame(RWSRCGLOBAL(curCamera)))); l = RwFrameGetMatrix(RpLightGetFrame(pDirect))->at; RwV3dTransformVector(&carfx_lightdir, &l, &carfx_view); RwV3dNormalize(&carfx_lightdir, &carfx_lightdir); RwMatrixInvert(&carfx_env1Inv, RwFrameGetLTM(carfx_env1Frame)); RwMatrixInvert(&carfx_env2Inv, RwFrameGetLTM(carfx_env2Frame)); } void CCustomCVCarEnvMapPipeline::SetupEnv(RxPS2AllPipeData *p2all, RwFrame *envframe, RwMatrix *frminv, RwMatrix *envmat) { static RwMatrix lastmat; static void *lastobject; static RwFrame *lastfrm; static RwUInt16 lastrenderframe; RpAtomic *atomic; RpClump *clump; RwFrame *frame; atomic = p2all->sourceObject; clump = RpAtomicGetClump(atomic); if(lastobject != (clump ? (void*)clump : (void*)atomic) || lastfrm != envframe || lastrenderframe != RWSRCGLOBAL(renderFrame)){ frame = clump ? RpClumpGetFrame(clump) : RpAtomicGetFrame(atomic); RwMatrixMultiply(&lastmat, RwFrameGetLTM(frame), frminv); lastobject = (clump ? (void*)clump : (void*)atomic); lastfrm = envframe; lastrenderframe = RWSRCGLOBAL(renderFrame); } *envmat = lastmat; } void CCustomCVCarEnvMapPipeline::SetupSpec(RxPS2AllPipeData *p2all, RwMatrix *specmat, RwV3d *specdir) { static RwMatrix lastmat; static RwV3d lastdir; static void *lastobject; static RwUInt16 lastrenderframe; RwFrame *frame; RpAtomic *atomic; atomic = p2all->sourceObject; if(lastobject != atomic) || lastrenderframe != ENGINE->renderFrame){ frame = RpAtomicGetFrame(atomic); RwMatrixMultiply(&lastmat, RwFrameGetLTM(frame), &carfx_view); lastdir = carfx_lightdir; lastobject = atomic); lastrenderframe = ENGINE->renderFrame; } *specdir = lastdir; *specmat = lastmat; } void CCustomCVCarEnvMapPipeline::Env1Xform(RxPS2AllPipeData *p2all, RwMatrix *envmat, CustomEnvMapPipeMaterialData *envData, float *envXform) { float sclx, scly; sclx = envData->transSclX/8.0f*50.0f; scly = envData->transSclY/8.0f*50.0f; envXform[0] = (envmat.pos.x - ((float)(int)(envmat.pos.x/sclx))*sclx)/sclx; envXform[1] = (envmat.pos.y - ((float)(int)(envmat.pos.y/scly))*scly)/scly; } inline float calcthing(float pos, float scl){ int i; float f; i = pos/scl; f = fabs((i*scl - pos)/scl); return i & 1 ? f : 1.0 - f; } void CCustomCVCarEnvMapPipeline::Env2Xform(RxPS2AllPipeData *p2all, RwMatrix *envmat, CustomEnvMapPipeMaterialData *envData, CustomEnvMapPipeAtomicData *atmEnvData, float *envXform) { static void *lastobject; static CustomEnvMapPipeMaterialData *lastenvdata; static RwUInt16 lastrenderframe; static float lastTransX, lastTransY; static float lastx, lasty; CVector diff, upnorm; float trans; float sclx, scly; float val1, val2; int sub; sclx = envData->transSclX/8.0f*50.0f; scly = envData->transSclY/8.0f*50.0f; if(lastrenderframe != RWSRCGLOBAL(renderFrame) || lastobject != p2all->sourceObject || lastenvdata != envData){ envData->renderFrameCounter = RWSRCGLOBAL(renderFrame); lastrenderframe = RWSRCGLOBAL(renderFrame); lastobject = p2all->sourceObject; lastenvdata = envData; val1 = calcthing(envmat->pos.x, sclx) + calcthing(envmat->pos.y, scly); val2 = calcthing(atmEnvData->posx, sclx) + calcthing(atmEnvData->posy, scly); diff = { atmEnvData->posx - envmat->pos.x, atmEnvData->posy - envmat->pos.y, 0.0 }; sub = 0; if(diff.lensq() > 0.0f){ diff.Normalize(); upnorm.x = envmat->up.x; upnorm.y = envmat->up.y; upnorm.z = envmat->up.z; upnorm.Normalize(); if(diff.dot(upnorm) < 0.0f) sub = 1; } if(sub){ trans = atmEnvData->trans - fabs(val2-val1); if(trans < 0.0f) trans += 1.0f; }else{ trans = atmEnvData->trans + fabs(val2-val1); if(trans >= 1.0f) trans -= 1.0f; } lastTransX = atmEnvData->trans = trans; lastTransY = envmat->at.x + envmat->at.y; if(lastTransY > 0.1) lastTransY = 0.1f; if(lastTransY < 0.0) lastTransY = 0.0f; if(envmat->at.z < 0.0f) lastTransY = 1.0 - lastTransY; lastx = atmEnvData->posx = envmat->pos.x; lasty = atmEnvData->posy = envmat->pos.y; }else{ atmEnvData->trans = lastTransX; atmEnvData->posx = lastx; atmEnvData->posy = lasty; } envXform[0] = lastTransX; envXform[1] = lastTransY; } RwBool CCustomCVCarEnvMapPipeline::BridgeCB(RxPS2AllPipeData *p2all) { RpMaterial *mat; RwTexture *tex; RpAtomic *atomic; int materialFlags; bool noFx; bool hasEnv1, hasEnv2, hasSpec; float lightmult; float shininess; float specularity; CustomEnvMapPipeMaterialData *envData; CustomEnvMapPipeAtomicData *atmEnvData; RwMatrix envmat; float envXform[4]; RwMatrix specmat; RwV3d specdir; mat = p2all->mesh->material; atomic = p2all->sourceObject; envData = *RWPLUGINOFFSET(CustomEnvMapPipeMaterialData*, mat, CCustomCVCarEnvMapPipeline__ms_envMapPluginOffset); /* --- ... */ noFx = !!(CVisibilityPlugins::GetAtomicId(atomic) & 0x6000); materialFlags = *(RwUInt32*)&material->surfaceProps.specular; hasEnv1 = !!(materialFlags & 1); hasEnv2 = !!(materialFlags & 2); hasSpec = !!(materialFlags & 4); if((hasEnv1 || hasEnv2) && !noFx){ tex = CCustomCVCarEnvMapPipeline::GetFxEnvTexture(mat); if(tex){ /* --- upload texture */ }else{ materialFlags &= ~3; hasEnv1 = 0; hasEnv2 = 0; } } if(hasSpec){ tex = CCustomCVCarEnvMapPipeline::GetFxSpecTexture(mat); if(tex){ /* --- upload texture */ }else{ materialFlags &= ~4; hasSpec = 0; } } RpMeshPS2AllSyncTextureUpload(p2all); /* --- */ lightmult = CCustomCVCarEnvMapPipeline::m_EnvMapLightingMult; shininess = envData->shininess/255.0; if(noFx){ shininess = 0; specularity = 0; materialFlags = 0; }else{ if(hasEnv1){ CCustomCVCarEnvMapPipeline::SetupEnv(p2all, carfx_env1Frame, &carfx_env1Inv, &envmat); CCustomCVCarEnvMapPipeline::Env1Xform(p2all, &envmat, envData, &envXform); }else{ atmEnvData = CCustomCVCarEnvMapPipeline::AllocEnvMapPipeAtomicData(atomic); if(atmEnvData){ CCustomCVCarEnvMapPipeline::SetupEnv(p2all, carfx_env2Frame, &carfx_env2Inv, &envmat); CCustomCVCarEnvMapPipeline::Env2Xform(p2all, &envmat, envData, atmEnvData, &envXform); }else materialFlags &= ~2; } envXform[2] = envData->scaleX/8.0f; envXform[3] = envData->scaleY/8.0f; if(hasSpec){ CCustomCVCarEnvMapPipeline::SetupSpec(p2all, &specmat, &specdir); specularity = CCustomCVCarEnvMapPipeline::GetFxSpecSpecularity(mat); } } /* * --- construct packet */ return TRUE; }