diff options
| author | claude-bot <[email protected]> | 2026-07-13 12:27:07 +0000 |
|---|---|---|
| committer | claude-bot <[email protected]> | 2026-07-13 12:27:07 +0000 |
| commit | 9f61c9e6ac6b1ac5692cf6352d2ebbd47a31a686 (patch) | |
| tree | a84756b82513739a2672db3a1f0ec579db6d18ff /src/modelinfo/VehicleModelInfo.cpp | |
| download | re3-9f61c9e6ac6b1ac5692cf6352d2ebbd47a31a686.tar.gz re3-9f61c9e6ac6b1ac5692cf6352d2ebbd47a31a686.zip | |
Snapshot import (no upstream history) into git.ancap.in.ua/claude, per @lzcnt.
Source: https://github.com/Cai1Hsu/re3 branch miami.
Diffstat (limited to 'src/modelinfo/VehicleModelInfo.cpp')
| -rw-r--r-- | src/modelinfo/VehicleModelInfo.cpp | 1193 |
1 files changed, 1193 insertions, 0 deletions
diff --git a/src/modelinfo/VehicleModelInfo.cpp b/src/modelinfo/VehicleModelInfo.cpp new file mode 100644 index 0000000..d31962c --- /dev/null +++ b/src/modelinfo/VehicleModelInfo.cpp @@ -0,0 +1,1193 @@ +#include "common.h" +#include <rpmatfx.h> + +#include "RwHelper.h" +#include "General.h" +#include "NodeName.h" +#include "TxdStore.h" +#include "Weather.h" +#include "HandlingMgr.h" +#include "VisibilityPlugins.h" +#include "FileMgr.h" +#include "World.h" +#include "Vehicle.h" +#include "Automobile.h" +#include "Boat.h" +#include "Train.h" +#include "Plane.h" +#include "Heli.h" +#include "Bike.h" +#include "ModelIndices.h" +#include "ModelInfo.h" +#include "custompipes.h" + +int8 CVehicleModelInfo::ms_compsToUse[2] = { -2, -2 }; +int8 CVehicleModelInfo::ms_compsUsed[2]; +RwRGBA CVehicleModelInfo::ms_vehicleColourTable[256]; +RwTexture *CVehicleModelInfo::ms_colourTextureTable[256]; + +RwTexture *gpWhiteTexture; +RwFrame *pMatFxIdentityFrame; + +enum { + VEHICLE_FLAG_COLLAPSE = 0x2, + VEHICLE_FLAG_ADD_WHEEL = 0x4, + VEHICLE_FLAG_POS = 0x8, + VEHICLE_FLAG_DOOR = 0x10, + VEHICLE_FLAG_LEFT = 0x20, + VEHICLE_FLAG_RIGHT = 0x40, + VEHICLE_FLAG_FRONT = 0x80, + VEHICLE_FLAG_REAR = 0x100, + VEHICLE_FLAG_COMP = 0x200, + VEHICLE_FLAG_DRAWLAST = 0x400, + VEHICLE_FLAG_WINDSCREEN = 0x800, + VEHICLE_FLAG_ANGLECULL = 0x1000, + VEHICLE_FLAG_REARDOOR = 0x2000, + VEHICLE_FLAG_FRONTDOOR = 0x4000, +}; + +RwObjectNameIdAssocation carIds[] = { + { "wheel_rf_dummy", CAR_WHEEL_RF, VEHICLE_FLAG_RIGHT | VEHICLE_FLAG_ADD_WHEEL }, + { "wheel_rm_dummy", CAR_WHEEL_RM, VEHICLE_FLAG_RIGHT | VEHICLE_FLAG_ADD_WHEEL }, + { "wheel_rb_dummy", CAR_WHEEL_RB, VEHICLE_FLAG_RIGHT | VEHICLE_FLAG_ADD_WHEEL }, + { "wheel_lf_dummy", CAR_WHEEL_LF, VEHICLE_FLAG_LEFT | VEHICLE_FLAG_ADD_WHEEL }, + { "wheel_lm_dummy", CAR_WHEEL_LM, VEHICLE_FLAG_LEFT | VEHICLE_FLAG_ADD_WHEEL }, + { "wheel_lb_dummy", CAR_WHEEL_LB, VEHICLE_FLAG_LEFT | VEHICLE_FLAG_ADD_WHEEL }, + { "bump_front_dummy", CAR_BUMP_FRONT, VEHICLE_FLAG_FRONT | VEHICLE_FLAG_COLLAPSE }, + { "bonnet_dummy", CAR_BONNET, VEHICLE_FLAG_COLLAPSE }, + { "wing_rf_dummy", CAR_WING_RF, VEHICLE_FLAG_COLLAPSE }, + { "wing_rr_dummy", CAR_WING_RR, VEHICLE_FLAG_RIGHT | VEHICLE_FLAG_COLLAPSE }, + { "door_rf_dummy", CAR_DOOR_RF, VEHICLE_FLAG_FRONTDOOR | VEHICLE_FLAG_ANGLECULL | VEHICLE_FLAG_RIGHT | VEHICLE_FLAG_DOOR | VEHICLE_FLAG_COLLAPSE }, + { "door_rr_dummy", CAR_DOOR_RR, VEHICLE_FLAG_REARDOOR | VEHICLE_FLAG_ANGLECULL | VEHICLE_FLAG_REAR | VEHICLE_FLAG_RIGHT | VEHICLE_FLAG_DOOR | VEHICLE_FLAG_COLLAPSE }, + { "wing_lf_dummy", CAR_WING_LF, VEHICLE_FLAG_COLLAPSE }, + { "wing_lr_dummy", CAR_WING_LR, VEHICLE_FLAG_LEFT | VEHICLE_FLAG_COLLAPSE }, + { "door_lf_dummy", CAR_DOOR_LF, VEHICLE_FLAG_FRONTDOOR | VEHICLE_FLAG_ANGLECULL | VEHICLE_FLAG_LEFT | VEHICLE_FLAG_DOOR | VEHICLE_FLAG_COLLAPSE }, + { "door_lr_dummy", CAR_DOOR_LR, VEHICLE_FLAG_REARDOOR | VEHICLE_FLAG_ANGLECULL | VEHICLE_FLAG_REAR | VEHICLE_FLAG_LEFT | VEHICLE_FLAG_DOOR | VEHICLE_FLAG_COLLAPSE }, + { "boot_dummy", CAR_BOOT, VEHICLE_FLAG_REAR | VEHICLE_FLAG_COLLAPSE }, + { "bump_rear_dummy", CAR_BUMP_REAR, VEHICLE_FLAG_REAR | VEHICLE_FLAG_COLLAPSE }, + { "windscreen_dummy", CAR_WINDSCREEN, VEHICLE_FLAG_WINDSCREEN | VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_FRONT | VEHICLE_FLAG_COLLAPSE }, + + { "ped_frontseat", CAR_POS_FRONTSEAT, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID }, + { "ped_backseat", CAR_POS_BACKSEAT, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID }, + { "headlights", CAR_POS_HEADLIGHTS, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID }, + { "taillights", CAR_POS_TAILLIGHTS, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID }, + { "exhaust", CAR_POS_EXHAUST, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID }, + { "extra1", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID }, + { "extra2", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID }, + { "extra3", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID }, + { "extra4", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID }, + { "extra5", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID }, + { "extra6", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID }, + { nil, 0, 0 } +}; + +RwObjectNameIdAssocation boatIds[] = { + { "boat_moving_hi", BOAT_MOVING, 0 }, + { "boat_rudder_hi", BOAT_RUDDER, 0 }, + { "boat_flap_left", BOAT_FLAP_LEFT, 0 }, + { "boat_flap_right", BOAT_FLAP_RIGHT, 0 }, + { "boat_rearflap_left", BOAT_REARFLAP_LEFT, 0 }, + { "boat_rearflap_right", BOAT_REARFLAP_RIGHT, 0 }, +#ifdef FIX_BUGS + // let's just accept both + { "windscreen", BOAT_WINDSCREEN, VEHICLE_FLAG_WINDSCREEN | VEHICLE_FLAG_DRAWLAST }, + { "windscreen_hi_ok", BOAT_WINDSCREEN, VEHICLE_FLAG_WINDSCREEN | VEHICLE_FLAG_DRAWLAST }, +#else +#ifdef GTA_PS2 + { "windscreen", BOAT_WINDSCREEN, VEHICLE_FLAG_WINDSCREEN | VEHICLE_FLAG_DRAWLAST }, +#else + { "windscreen_hi_ok", BOAT_WINDSCREEN, VEHICLE_FLAG_WINDSCREEN | VEHICLE_FLAG_DRAWLAST }, +#endif +#endif + { "ped_frontseat", BOAT_POS_FRONTSEAT, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID }, + { nil, 0, 0 } +}; + +RwObjectNameIdAssocation trainIds[] = { + { "door_lhs_dummy", TRAIN_DOOR_LHS, VEHICLE_FLAG_LEFT | VEHICLE_FLAG_COLLAPSE }, + { "door_rhs_dummy", TRAIN_DOOR_RHS, VEHICLE_FLAG_LEFT | VEHICLE_FLAG_COLLAPSE }, + { "light_front", TRAIN_POS_LIGHT_FRONT, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID }, + { "light_rear", TRAIN_POS_LIGHT_REAR, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID }, + { "ped_left_entry", TRAIN_POS_LEFT_ENTRY, VEHICLE_FLAG_DOOR | VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID }, + { "ped_mid_entry", TRAIN_POS_MID_ENTRY, VEHICLE_FLAG_DOOR | VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID }, + { "ped_right_entry", TRAIN_POS_RIGHT_ENTRY, VEHICLE_FLAG_DOOR | VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID }, + { nil, 0, 0 } +}; + +RwObjectNameIdAssocation heliIds[] = { + { "chassis_dummy", HELI_CHASSIS, VEHICLE_FLAG_COLLAPSE }, + { "toprotor", HELI_TOPROTOR, 0 }, + { "backrotor", HELI_BACKROTOR, 0 }, + { "tail", HELI_TAIL, 0 }, + { "topknot", HELI_TOPKNOT, 0 }, + { "skid_left", HELI_SKID_LEFT, 0 }, + { "skid_right", HELI_SKID_RIGHT, 0 }, + { nil, 0, 0 } +}; + +RwObjectNameIdAssocation planeIds[] = { + { "wheel_front_dummy", PLANE_WHEEL_FRONT, 0 }, + { "wheel_rear_dummy", PLANE_WHEEL_READ, 0 }, + { "light_tailplane", PLANE_POS_LIGHT_TAIL, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID }, + { "light_left", PLANE_POS_LIGHT_LEFT, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID }, + { "light_right", PLANE_POS_LIGHT_RIGHT, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID }, + { nil, 0, 0 } +}; + +RwObjectNameIdAssocation bikeIds[] = { + { "chassis_dummy", BIKE_CHASSIS, 0 }, + { "forks_front", BIKE_FORKS_FRONT, 0 }, + { "forks_rear", BIKE_FORKS_REAR, 0 }, + { "wheel_front", BIKE_WHEEL_FRONT, 0 }, + { "wheel_rear", BIKE_WHEEL_REAR, 0 }, + { "mudguard", BIKE_MUDGUARD, 0 }, + { "handlebars", BIKE_HANDLEBARS, 0 }, + { "ped_frontseat", CAR_POS_FRONTSEAT, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID }, + { "ped_backseat", CAR_POS_BACKSEAT, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID }, + { "headlights", CAR_POS_HEADLIGHTS, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID }, + { "taillights", CAR_POS_TAILLIGHTS, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID }, + { "exhaust", CAR_POS_EXHAUST, VEHICLE_FLAG_POS | CLUMP_FLAG_NO_HIERID }, + { "extra1", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID }, + { "extra2", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID }, + { "extra3", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID }, + { "extra4", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID }, + { "extra5", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID }, + { "extra6", 0, VEHICLE_FLAG_DRAWLAST | VEHICLE_FLAG_COMP | CLUMP_FLAG_NO_HIERID }, + { nil, 0, 0 } +}; + +RwObjectNameIdAssocation *CVehicleModelInfo::ms_vehicleDescs[] = { + carIds, + boatIds, + trainIds, + heliIds, + planeIds, + bikeIds +}; + +bool gbBlackCars; +bool gbPinkCars; + +CVehicleModelInfo::CVehicleModelInfo(void) + : CClumpModelInfo(MITYPE_VEHICLE) +{ + int32 i; + for(i = 0; i < NUM_VEHICLE_POSITIONS; i++){ + m_positions[i].x = 0.0f; + m_positions[i].y = 0.0f; + m_positions[i].z = 0.0f; + } + m_numColours = 0; + m_animFileIndex = -1; +} + +void +CVehicleModelInfo::DeleteRwObject(void) +{ + int32 i; + RwFrame *f; + + for(i = 0; i < m_numComps; i++){ + f = RpAtomicGetFrame(m_comps[i]); + RpAtomicDestroy(m_comps[i]); + RwFrameDestroy(f); + } + m_numComps = 0; + CClumpModelInfo::DeleteRwObject(); +} + +RwObject* +CVehicleModelInfo::CreateInstance(void) +{ + RpClump *clump; + RpAtomic *atomic; + RwFrame *clumpframe, *f; + int32 comp1, comp2; + + clump = (RpClump*)CClumpModelInfo::CreateInstance(); + if(m_numComps != 0){ + clumpframe = RpClumpGetFrame(clump); + + comp1 = ChooseComponent(); + if(comp1 != -1 && m_comps[comp1]){ + atomic = RpAtomicClone(m_comps[comp1]); + f = RwFrameCreate(); + RwFrameTransform(f, + RwFrameGetMatrix(RpAtomicGetFrame(m_comps[comp1])), + rwCOMBINEREPLACE); + RpAtomicSetFrame(atomic, f); + RpClumpAddAtomic(clump, atomic); + RwFrameAddChild(clumpframe, f); + } + ms_compsUsed[0] = comp1; + + comp2 = ChooseSecondComponent(); + if(comp2 != -1 && m_comps[comp2]){ + atomic = RpAtomicClone(m_comps[comp2]); + f = RwFrameCreate(); + RwFrameTransform(f, + RwFrameGetMatrix(RpAtomicGetFrame(m_comps[comp2])), + rwCOMBINEREPLACE); + RpAtomicSetFrame(atomic, f); + RpClumpAddAtomic(clump, atomic); + RwFrameAddChild(clumpframe, f); + } + ms_compsUsed[1] = comp2; + }else{ + ms_compsUsed[0] = -1; + ms_compsUsed[1] = -1; + } + return (RwObject*)clump; +} + +void +CVehicleModelInfo::SetClump(RpClump *clump) +{ + CClumpModelInfo::SetClump(clump); + SetAtomicRenderCallbacks(); + SetFrameIds(ms_vehicleDescs[m_vehicleType]); + PreprocessHierarchy(); + FindEditableMaterialList(); + SetEnvironmentMap(); +} + +void +CVehicleModelInfo::SetAnimFile(const char *file) +{ + if(strcasecmp(file, "null") == 0) + return; + + m_animFileName = new char[strlen(file)+1]; + strcpy(m_animFileName, file); +} + +void +CVehicleModelInfo::ConvertAnimFileIndex(void) +{ + if(m_animFileIndex != -1){ + // we have a string pointer in that union + int32 index = CAnimManager::GetAnimationBlockIndex(m_animFileName); + delete[] m_animFileName; + m_animFileIndex = index; + } +} + +RwFrame* +CVehicleModelInfo::CollapseFramesCB(RwFrame *frame, void *data) +{ + RwFrameForAllChildren(frame, CollapseFramesCB, data); + RwFrameForAllObjects(frame, MoveObjectsCB, data); + RwFrameDestroy(frame); + return frame; +} + +RwObject* +CVehicleModelInfo::MoveObjectsCB(RwObject *object, void *data) +{ + RpAtomicSetFrame((RpAtomic*)object, (RwFrame*)data); + return object; +} + +RpAtomic* +CVehicleModelInfo::HideDamagedAtomicCB(RpAtomic *atomic, void *data) +{ + if(strstr(GetFrameNodeName(RpAtomicGetFrame(atomic)), "_dam")){ + RpAtomicSetFlags(atomic, 0); + CVisibilityPlugins::SetAtomicFlag(atomic, ATOMIC_FLAG_DAM); + }else if(strstr(GetFrameNodeName(RpAtomicGetFrame(atomic)), "_ok")) + CVisibilityPlugins::SetAtomicFlag(atomic, ATOMIC_FLAG_OK); + return atomic; +} + +RpAtomic* +CVehicleModelInfo::HideAllComponentsAtomicCB(RpAtomic *atomic, void *data) +{ + if(CVisibilityPlugins::GetAtomicId(atomic) & (uintptr)data) + RpAtomicSetFlags(atomic, 0); + else + RpAtomicSetFlags(atomic, rpATOMICRENDER); + return atomic; +} + +RpMaterial* +CVehicleModelInfo::HasAlphaMaterialCB(RpMaterial *material, void *data) +{ + if(RpMaterialGetColor(material)->alpha != 0xFF){ + *(bool*)data = true; + return nil; + } + return material; +} + + +RpAtomic* +CVehicleModelInfo::SetAtomicRendererCB(RpAtomic *atomic, void *data) +{ + RpClump *clump; + char *name; + bool alpha; + + clump = (RpClump*)data; + name = GetFrameNodeName(RpAtomicGetFrame(atomic)); + alpha = false; + RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), HasAlphaMaterialCB, &alpha); + if(strstr(name, "_hi") || !CGeneral::faststrncmp(name, "extra", 5)) { + if(alpha || strncmp(name, "windscreen", 10) == 0) + CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailAlphaCB); + else + CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailCB); + }else if(strstr(name, "_lo")){ + RpClumpRemoveAtomic(clump, atomic); + RpAtomicDestroy(atomic); + return atomic; // BUG: nil in gta + }else if(strstr(name, "_vlo")) + CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleReallyLowDetailCB); + else + CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil); + HideDamagedAtomicCB(atomic, nil); + return atomic; +} + +RpAtomic* +CVehicleModelInfo::SetAtomicRendererCB_BigVehicle(RpAtomic *atomic, void *data) +{ + char *name; + bool alpha; + + name = GetFrameNodeName(RpAtomicGetFrame(atomic)); + alpha = false; + RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), HasAlphaMaterialCB, &alpha); + if(strstr(name, "_hi") || !CGeneral::faststrncmp(name, "extra", 5)) { + if(alpha) + CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailAlphaCB_BigVehicle); + else + CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailCB_BigVehicle); + }else if(strstr(name, "_lo")){ + if(alpha) + CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleLowDetailAlphaCB_BigVehicle); + else + CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleLowDetailCB_BigVehicle); + }else if(strstr(name, "_vlo")) + CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleReallyLowDetailCB_BigVehicle); + else + CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil); + HideDamagedAtomicCB(atomic, nil); + return atomic; +} + +RpAtomic* +CVehicleModelInfo::SetAtomicRendererCB_Train(RpAtomic *atomic, void *data) +{ + char *name; + bool alpha; + + name = GetFrameNodeName(RpAtomicGetFrame(atomic)); + alpha = false; + RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), HasAlphaMaterialCB, &alpha); + if(strstr(name, "_hi")){ + if(alpha) + CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderTrainHiDetailAlphaCB); + else + CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderTrainHiDetailCB); + }else if(strstr(name, "_vlo")) + CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleReallyLowDetailCB_BigVehicle); + else + CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil); + HideDamagedAtomicCB(atomic, nil); + return atomic; +} + +RpAtomic* +CVehicleModelInfo::SetAtomicRendererCB_Boat(RpAtomic *atomic, void *data) +{ + RpClump *clump; + char *name; + bool alpha; + + clump = (RpClump*)data; + name = GetFrameNodeName(RpAtomicGetFrame(atomic)); + alpha = false; + RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), HasAlphaMaterialCB, &alpha); + if(strcmp(name, "boat_hi") == 0 || !CGeneral::faststrncmp(name, "extra", 5)) + CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailCB_Boat); + else if(strstr(name, "_hi")){ + if(alpha) + CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailAlphaCB_Boat); + else + CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailCB); + }else if(strstr(name, "_lo")){ + RpClumpRemoveAtomic(clump, atomic); + RpAtomicDestroy(atomic); + return atomic; // BUG: not done by gta + }else if(strstr(name, "_vlo")) + CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleLoDetailCB_Boat); + else{ + if(alpha) + CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailAlphaCB_Boat); + else + CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil); + } + HideDamagedAtomicCB(atomic, nil); + return atomic; +} + +RpAtomic* +CVehicleModelInfo::SetAtomicRendererCB_Heli(RpAtomic *atomic, void *data) +{ + char *name; + + name = GetFrameNodeName(RpAtomicGetFrame(atomic)); + if(strncmp(name, "toprotor", 8) == 0) + CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleRotorAlphaCB); + else if(strncmp(name, "rearrotor", 9) == 0) + CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleTailRotorAlphaCB); + else + CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil); + return atomic; +} + +RpAtomic* +CVehicleModelInfo::SetAtomicRendererCB_RealHeli(RpAtomic *atomic, void *data) +{ + RpClump *clump; + char *name; + bool alpha; + + clump = (RpClump*)data; + name = GetFrameNodeName(RpAtomicGetFrame(atomic)); + alpha = false; + RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), HasAlphaMaterialCB, &alpha); + if(strncmp(name, "toprotor", 8) == 0) + CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleRotorAlphaCB); + else if(strncmp(name, "rearrotor", 9) == 0) + CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleTailRotorAlphaCB); + else if(strstr(name, "_hi") || !CGeneral::faststrncmp(name, "extra", 5)) { + if(alpha || strncmp(name, "windscreen", 10) == 0) + CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailAlphaCB); + else + CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleHiDetailCB); + }else if(strstr(name, "_lo")){ + RpClumpRemoveAtomic(clump, atomic); + RpAtomicDestroy(atomic); + return atomic; // BUG: nil in gta + }else if(strstr(name, "_vlo")) + CVisibilityPlugins::SetAtomicRenderCallback(atomic, CVisibilityPlugins::RenderVehicleReallyLowDetailCB); + else + CVisibilityPlugins::SetAtomicRenderCallback(atomic, nil); + HideDamagedAtomicCB(atomic, nil); + return atomic; +} + +void +CVehicleModelInfo::SetAtomicRenderCallbacks(void) +{ +#ifdef GTA_TRAIN + if(m_vehicleType == VEHICLE_TYPE_TRAIN) + RpClumpForAllAtomics(m_clump, SetAtomicRendererCB_Train, nil); + else +#endif + if(m_vehicleType == VEHICLE_TYPE_HELI) + RpClumpForAllAtomics(m_clump, SetAtomicRendererCB_Heli, nil); + else if(m_vehicleType == VEHICLE_TYPE_PLANE) + RpClumpForAllAtomics(m_clump, SetAtomicRendererCB_BigVehicle, nil); + else if(m_vehicleType == VEHICLE_TYPE_BOAT) + RpClumpForAllAtomics(m_clump, SetAtomicRendererCB_Boat, m_clump); + else if(mod_HandlingManager.GetHandlingData((tVehicleType)m_handlingId)->Flags & HANDLING_IS_HELI) + RpClumpForAllAtomics(m_clump, SetAtomicRendererCB_RealHeli, m_clump); + else + RpClumpForAllAtomics(m_clump, SetAtomicRendererCB, m_clump); +} + +RwObject* +CVehicleModelInfo::SetAtomicFlagCB(RwObject *object, void *data) +{ + RpAtomic *atomic = (RpAtomic*)object; + assert(RwObjectGetType(object) == rpATOMIC); + CVisibilityPlugins::SetAtomicFlag(atomic, (uintptr)data); + return object; +} + +RwObject* +CVehicleModelInfo::ClearAtomicFlagCB(RwObject *object, void *data) +{ + RpAtomic *atomic = (RpAtomic*)object; + assert(RwObjectGetType(object) == rpATOMIC); + CVisibilityPlugins::ClearAtomicFlag(atomic, (uintptr)data); + return object; +} + +RwObject* +GetOkAndDamagedAtomicCB(RwObject *object, void *data) +{ + RpAtomic *atomic = (RpAtomic*)object; + if(CVisibilityPlugins::GetAtomicId(atomic) & ATOMIC_FLAG_OK) + ((RpAtomic**)data)[0] = atomic; + else if(CVisibilityPlugins::GetAtomicId(atomic) & ATOMIC_FLAG_DAM) + ((RpAtomic**)data)[1] = atomic; + return object; +} + +void +CVehicleModelInfo::PreprocessHierarchy(void) +{ + int32 i; + RwObjectNameIdAssocation *desc; + RwFrame *f; + RpAtomic *atomic; + RwV3d *rwvec; + + desc = ms_vehicleDescs[m_vehicleType]; + m_numDoors = 0; + m_numComps = 0; + + for(i = 0; desc[i].name; i++){ + RwObjectNameAssociation assoc; + + if((desc[i].flags & (VEHICLE_FLAG_COMP|VEHICLE_FLAG_POS)) == 0) + continue; + assoc.frame = nil; + assoc.name = desc[i].name; + RwFrameForAllChildren(RpClumpGetFrame(m_clump), + FindFrameFromNameWithoutIdCB, &assoc); + if(assoc.frame == nil) + continue; + + if(desc[i].flags & VEHICLE_FLAG_DOOR) + m_numDoors++; + + if(desc[i].flags & VEHICLE_FLAG_POS){ + f = assoc.frame; + rwvec = &m_positions[desc[i].hierId]; + *rwvec = *RwMatrixGetPos(RwFrameGetMatrix(f)); + for(f = RwFrameGetParent(f); f; f = RwFrameGetParent(f)) + RwV3dTransformPoints(rwvec, rwvec, 1, RwFrameGetMatrix(f)); + RwFrameDestroy(assoc.frame); + }else{ + atomic = (RpAtomic*)GetFirstObject(assoc.frame); + RpClumpRemoveAtomic(m_clump, atomic); + RwFrameRemoveChild(assoc.frame); + SetVehicleComponentFlags(assoc.frame, desc[i].flags); + m_comps[m_numComps++] = atomic; + } + } + + for(i = 0; desc[i].name; i++){ + RwObjectIdAssociation assoc; + + if(desc[i].flags & (VEHICLE_FLAG_COMP|VEHICLE_FLAG_POS)) + continue; + assoc.frame = nil; + assoc.id = desc[i].hierId; + RwFrameForAllChildren(RpClumpGetFrame(m_clump), + FindFrameFromIdCB, &assoc); + if(assoc.frame == nil) + continue; + + if(desc[i].flags & VEHICLE_FLAG_DOOR) + m_numDoors++; + + if(desc[i].flags & VEHICLE_FLAG_COLLAPSE){ + RpAtomic *okdam[2] = { nil, nil }; + RwFrameForAllChildren(assoc.frame, CollapseFramesCB, assoc.frame); + RwFrameUpdateObjects(assoc.frame); + RwFrameForAllObjects(assoc.frame, GetOkAndDamagedAtomicCB, okdam); + if(okdam[0] && okdam[1]) + RpAtomicSetRenderCallBack(okdam[1], RpAtomicGetRenderCallBack(okdam[0])); + } + + SetVehicleComponentFlags(assoc.frame, desc[i].flags); + + if(desc[i].flags & VEHICLE_FLAG_ADD_WHEEL){ + if(m_wheelId == -1) + RwFrameDestroy(assoc.frame); + else{ + RwV3d scale; + atomic = (RpAtomic*)CModelInfo::GetModelInfo(m_wheelId)->CreateInstance(); + RwFrameDestroy(RpAtomicGetFrame(atomic)); + RpAtomicSetFrame(atomic, assoc.frame); + RpClumpAddAtomic(m_clump, atomic); + CVisibilityPlugins::SetAtomicRenderCallback(atomic, + CVisibilityPlugins::RenderWheelAtomicCB); + scale.x = m_wheelScale; + scale.y = m_wheelScale; + scale.z = m_wheelScale; + RwFrameScale(assoc.frame, &scale, rwCOMBINEPRECONCAT); + } + } + } +} + +void +CVehicleModelInfo::SetVehicleComponentFlags(RwFrame *frame, uint32 flags) +{ + tHandlingData *handling; + + handling = mod_HandlingManager.GetHandlingData((tVehicleType)m_handlingId); + +#define SETFLAGS(f) RwFrameForAllObjects(frame, SetAtomicFlagCB, (void*)(f)) + + if(flags & VEHICLE_FLAG_WINDSCREEN){ + if(this == CModelInfo::GetModelInfo(MI_RHINO)) + return; + SETFLAGS(ATOMIC_FLAG_WINDSCREEN); + } + + if(flags & VEHICLE_FLAG_ANGLECULL) + SETFLAGS(ATOMIC_FLAG_ANGLECULL); + + if(flags & VEHICLE_FLAG_FRONT) + SETFLAGS(ATOMIC_FLAG_FRONT); + else if(flags & VEHICLE_FLAG_REAR && (handling->Flags & HANDLING_IS_VAN || (flags & (VEHICLE_FLAG_LEFT|VEHICLE_FLAG_RIGHT)) == 0)) + SETFLAGS(ATOMIC_FLAG_REAR); + else if(flags & VEHICLE_FLAG_LEFT) + SETFLAGS(ATOMIC_FLAG_LEFT); + else if(flags & VEHICLE_FLAG_RIGHT) + SETFLAGS(ATOMIC_FLAG_RIGHT); + + if(flags & VEHICLE_FLAG_REARDOOR) + SETFLAGS(ATOMIC_FLAG_REARDOOR); + else if(flags & VEHICLE_FLAG_FRONTDOOR) + SETFLAGS(ATOMIC_FLAG_FRONTDOOR); + + if(flags & VEHICLE_FLAG_DRAWLAST) + SETFLAGS(ATOMIC_FLAG_DRAWLAST); +} + +#define COMPRULE_RULE(comprule) (((comprule) >> 12) & 0xF) +#define COMPRULE_COMPS(comprule) ((comprule) & 0xFFF) +#define COMPRULE_COMPN(comps, n) (((comps) >> 4*(n)) & 0xF) +#define COMPRULE2_RULE(comprule) (((comprule) >> (12+16)) & 0xF) +#define COMPRULE2_COMPS(comprule) ((comprule >> 16) & 0xFFF) +#define COMPRULE2_COMPN(comps, n) (((comps >> 16) >> 4*(n)) & 0xF) + +bool +IsValidCompRule(int rule) +{ + if(rule == 2) + return CWeather::OldWeatherType == WEATHER_RAINY || + CWeather::NewWeatherType == WEATHER_RAINY; + return true; +} + +int32 +CountCompsInRule(int comps) +{ + int32 n; + for(n = 0; comps != 0; comps >>= 4) + if((comps & 0xF) != 0xF) + n++; + return n; +} + +int32 +ChooseComponent(int32 rule, int32 comps) +{ + int32 n; + switch(rule){ + // identical cases.... + case 1: + n = CGeneral::GetRandomNumberInRange(0, CountCompsInRule(comps)); + return COMPRULE_COMPN(comps, n); + case 2: + // only valid in rain + n = CGeneral::GetRandomNumberInRange(0, CountCompsInRule(comps)); + return COMPRULE_COMPN(comps, n); + case 3: + n = CGeneral::GetRandomNumberInRange(0, 1+CountCompsInRule(comps)); + if(n != 0) + return COMPRULE_COMPN(comps, n-1); + return -1; + case 4: +#ifdef FIX_BUGS + return CGeneral::GetRandomNumberInRange(0, 6); +#else + return CGeneral::GetRandomNumberInRange(0, 5); +#endif + } + return -1; +} + +int32 +GetListOfComponentsNotUsedByRules(uint32 comprules, int32 numComps, int32 *comps) +{ + int32 i, n; + int32 unused[6] = { 0, 1, 2, 3, 4, 5 }; + + // first comprule + if(COMPRULE_RULE(comprules) && IsValidCompRule(COMPRULE_RULE(comprules))) + for(i = 0; i < 3; i++){ + n = COMPRULE_COMPN(comprules, i); + if(n != 0xF) + unused[n] = 0xF; + } + // second comprule + comprules >>= 16; + if(COMPRULE_RULE(comprules) && IsValidCompRule(COMPRULE_RULE(comprules))) + for(i = 0; i < 3; i++){ + n = COMPRULE_COMPN(comprules, i); + if(n != 0xF) + unused[n] = 0xF; + } + + n = 0; + for(i = 0; i < numComps; i++) + if(unused[i] != 0xF) + comps[n++] = unused[i]; + return n; +} + +int32 wheelIds[] = { CAR_WHEEL_LF, CAR_WHEEL_LB, CAR_WHEEL_RF, CAR_WHEEL_RB }; + +void +CVehicleModelInfo::GetWheelPosn(int32 n, CVector &pos) +{ + RwMatrix *m = RwFrameGetMatrix(GetFrameFromId(m_clump, wheelIds[n])); + pos.x = RwMatrixGetPos(m)->x; + pos.y = RwMatrixGetPos(m)->y; + pos.z = RwMatrixGetPos(m)->z; +} + + +int32 +CVehicleModelInfo::ChooseComponent(void) +{ + int32 comp; + int32 comps[8]; + int32 n; + + comp = -1; + if(ms_compsToUse[0] == -2){ + if(COMPRULE_RULE(m_compRules) && IsValidCompRule(COMPRULE_RULE(m_compRules))) + comp = ::ChooseComponent(COMPRULE_RULE(m_compRules), COMPRULE_COMPS(m_compRules)); + else if(CGeneral::GetRandomNumberInRange(0, 3) < 2){ + n = GetListOfComponentsNotUsedByRules(m_compRules, m_numComps, comps); + if(n) + comp = comps[(int)CGeneral::GetRandomNumberInRange(0, n)]; + } + }else{ + comp = ms_compsToUse[0]; + ms_compsToUse[0] = -2; + } + return comp; +} + +int32 +CVehicleModelInfo::ChooseSecondComponent(void) +{ + int32 comp; + int32 comps[8]; + int32 n; + + comp = -1; + if(ms_compsToUse[1] == -2){ + if(COMPRULE2_RULE(m_compRules) && IsValidCompRule(COMPRULE2_RULE(m_compRules))) + comp = ::ChooseComponent(COMPRULE2_RULE(m_compRules), COMPRULE2_COMPS(m_compRules)); + else if(COMPRULE_RULE(m_compRules) && IsValidCompRule(COMPRULE_RULE(m_compRules)) && + CGeneral::GetRandomNumberInRange(0, 3) < 2){ + + n = GetListOfComponentsNotUsedByRules(m_compRules, m_numComps, comps); + if(n) + comp = comps[(int)CGeneral::GetRandomNumberInRange(0, n)]; + } + }else{ + comp = ms_compsToUse[1]; + ms_compsToUse[1] = -2; + } + return comp; +} + +struct editableMatCBData +{ + CVehicleModelInfo *vehicle; + int32 numMats1; + int32 numMats2; +}; + +RpMaterial* +CVehicleModelInfo::GetEditableMaterialListCB(RpMaterial *material, void *data) +{ + RwRGBA white = { 255, 255, 255, 255 }; + const RwRGBA *col; + editableMatCBData *cbdata; + + cbdata = (editableMatCBData*)data; + col = RpMaterialGetColor(material); + if(col->red == 0x3C && col->green == 0xFF && col->blue == 0){ + cbdata->vehicle->m_materials1[cbdata->numMats1++] = material; + RpMaterialSetColor(material, &white); + }else if(col->red == 0xFF && col->green == 0 && col->blue == 0xAF){ + cbdata->vehicle->m_materials2[cbdata->numMats2++] = material; + RpMaterialSetColor(material, &white); + } + return material; +} + +RpAtomic* +CVehicleModelInfo::GetEditableMaterialListCB(RpAtomic *atomic, void *data) +{ + RpGeometryForAllMaterials(RpAtomicGetGeometry(atomic), GetEditableMaterialListCB, data); + return atomic; +} + +static int maxFirstMaterials; +static int maxSecondMaterials; + +void +CVehicleModelInfo::FindEditableMaterialList(void) +{ + editableMatCBData cbdata; + int32 i; + + cbdata.vehicle = this; + cbdata.numMats1 = 0; + cbdata.numMats2 = 0; + RpClumpForAllAtomics(m_clump, GetEditableMaterialListCB, &cbdata); + for(i = 0; i < m_numComps; i++) + GetEditableMaterialListCB(m_comps[i], &cbdata); + m_materials1[cbdata.numMats1] = nil; + m_materials2[cbdata.numMats2] = nil; + maxFirstMaterials = Max(maxFirstMaterials, cbdata.numMats1); + maxSecondMaterials = Max(maxSecondMaterials, cbdata.numMats2); + m_currentColour1 = -1; + m_currentColour2 = -1; +} + +void +CVehicleModelInfo::SetVehicleColour(uint8 c1, uint8 c2) +{ + RwRGBA col, *colp; + RpMaterial **matp; + + if(c1 != m_currentColour1){ + col = ms_vehicleColourTable[c1]; + for(matp = m_materials1; *matp; matp++){ + colp = (RwRGBA*)RpMaterialGetColor(*matp); // get rid of const + colp->red = col.red; + colp->green = col.green; + colp->blue = col.blue; + } + m_currentColour1 = c1; + } + + if(c2 != m_currentColour2){ + col = ms_vehicleColourTable[c2]; + for(matp = m_materials2; *matp; matp++){ + colp = (RwRGBA*)RpMaterialGetColor(*matp); // get rid of const + colp->red = col.red; + colp->green = col.green; + colp->blue = col.blue; + } + m_currentColour2 = c2; + } +} + +void +CVehicleModelInfo::ChooseVehicleColour(uint8 &col1, uint8 &col2) +{ + if(m_numColours == 0 || gbBlackCars){ + col1 = 0; + col2 = 0; + }else if(gbPinkCars){ + col1 = 68; + col2 = 68; + }else{ + m_lastColorVariation = (m_lastColorVariation+1) % m_numColours; + col1 = m_colours1[m_lastColorVariation]; + col2 = m_colours2[m_lastColorVariation]; + if(m_numColours > 1){ + CVehicle *veh = FindPlayerVehicle(); + if(veh && CModelInfo::GetModelInfo(veh->GetModelIndex()) == this && + veh->m_currentColour1 == col1 && + veh->m_currentColour2 == col2){ + m_lastColorVariation = (m_lastColorVariation+1) % m_numColours; + col1 = m_colours1[m_lastColorVariation]; + col2 = m_colours2[m_lastColorVariation]; + } + } + } +} + +void +CVehicleModelInfo::AvoidSameVehicleColour(uint8 *col1, uint8 *col2) +{ + int i, n; + + if(gbBlackCars){ + *col1 = 0; + *col2 = 0; + }else if(gbPinkCars){ + *col1 = 68; + *col2 = 68; + }else{ + if(m_numColours > 1) + for(i = 0; i < 8; i++){ + if(*col1 != m_lastColour1 || *col2 != m_lastColour2) + break; + n = CGeneral::GetRandomNumberInRange(0, m_numColours); + *col1 = m_colours1[n]; + *col2 = m_colours2[n]; + } + m_lastColour1 = *col1; + m_lastColour2 = *col2; + } +} + +// unused +RwTexture* +CreateCarColourTexture(uint8 r, uint8 g, uint8 b) +{ + RwImage *img; + RwRaster *ras; + RwTexture *tex; + RwUInt8 *pixels; + RwInt32 width, height, depth, format; + + img = RwImageCreate(2, 2, 32); + pixels = (RwUInt8*)RwMalloc(2*2*4); + pixels[0] = r; + pixels[1] = g; + pixels[2] = b; + pixels[3] = 0xFF; + pixels[4] = r; + pixels[5] = g; + pixels[6] = b; + pixels[7] = 0xFF; + pixels[8] = r; + pixels[9] = g; + pixels[10] = b; + pixels[11] = 0xFF; + pixels[12] = r; + pixels[13] = g; + pixels[14] = b; + pixels[15] = 0xFF; + RwImageSetPixels(img, pixels); + RwImageSetStride(img, 8); + RwImageSetPalette(img, nil); + RwImageFindRasterFormat(img, rwRASTERTYPETEXTURE, &width, &height, &depth, &format); + ras = RwRasterCreate(width, height, depth, format); + RwRasterSetFromImage(ras, img); + RwImageDestroy(img); + RwFree(pixels); + tex = RwTextureCreate(ras); + RwTextureGetName(tex)[0] = '@'; + return tex; +} + +void +CVehicleModelInfo::LoadVehicleColours(void) +{ + int fd; + int i; + char line[1024]; + int start, end; + int section, numCols; + enum { + NONE, + COLOURS, + CARS + }; + int r, g, b; + char name[64]; + int colors[16]; + int n; + + CFileMgr::ChangeDir("\\DATA\\"); + fd = CFileMgr::OpenFile("CARCOLS.DAT", "r"); + CFileMgr::ChangeDir("\\"); + + for(i = 0; i < 256; i++) + ms_colourTextureTable[i] = nil; + + section = 0; + numCols = 0; + while(CFileMgr::ReadLine(fd, line, sizeof(line))){ + // find first valid character in line + for(start = 0; ; start++) + if(line[start] > ' ' || line[start] == '\0' || line[start] == '\n') + break; + // find end of line + for(end = start; ; end++){ + if(line[end] == '\0' || line[end] == '\n') + break; + if(line[end] == ',' || line[end] == '\r') + line[end] = ' '; + } + line[end] = '\0'; + + // empty line + if(line[start] == '#' || line[start] == '\0') + continue; + + if(section == NONE){ + if(line[start] == 'c' && line[start + 1] == 'o' && line[start + 2] == 'l') + section = COLOURS; + if(line[start] == 'c' && line[start + 1] == 'a' && line[start + 2] == 'r') + section = CARS; + }else if(line[start] == 'e' && line[start + 1] == 'n' && line[start + 2] == 'd'){ + section = NONE; + }else if(section == COLOURS){ + sscanf(&line[start], // BUG: games doesn't add start + "%d %d %d", &r, &g, &b); + ms_vehicleColourTable[numCols].red = r; + ms_vehicleColourTable[numCols].green = g; + ms_vehicleColourTable[numCols].blue = b; + ms_vehicleColourTable[numCols].alpha = 0xFF; + numCols++; + }else if(section == CARS){ + n = sscanf(&line[start], // BUG: games doesn't add start + "%s %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d", + name, + &colors[0], &colors[1], + &colors[2], &colors[3], + &colors[4], &colors[5], + &colors[6], &colors[7], + &colors[8], &colors[9], + &colors[10], &colors[11], + &colors[12], &colors[13], + &colors[14], &colors[15]); + CVehicleModelInfo *mi = (CVehicleModelInfo*)CModelInfo::GetModelInfo(name, nil); + assert(mi); + mi->m_numColours = (n-1)/2; + for(i = 0; i < mi->m_numColours; i++){ + mi->m_colours1[i] = colors[i*2 + 0]; + mi->m_colours2[i] = colors[i*2 + 1]; + } + } + } + + CFileMgr::CloseFile(fd); +} + +void +CVehicleModelInfo::DeleteVehicleColourTextures(void) +{ + int i; + + for(i = 0; i < 256; i++){ + if(ms_colourTextureTable[i]){ + RwTextureDestroy(ms_colourTextureTable[i]); + ms_colourTextureTable[i] = nil; + } + } +} + +RpMaterial* +CVehicleModelInfo::GetMatFXEffectMaterialCB(RpMaterial *material, void *data) +{ + if(RpMatFXMaterialGetEffects(material) == rpMATFXEFFECTNULL) + return material; + *(int*)data = RpMatFXMaterialGetEffects(material); + return nil; +} + +RpMaterial* +CVehicleModelInfo::SetDefaultEnvironmentMapCB(RpMaterial *material, void *data) +{ + if(RpMatFXMaterialGetEffects(material) == rpMATFXEFFECTENVMAP){ + RpMatFXMaterialSetEnvMapFrame(material, pMatFxIdentityFrame); + if(RpMaterialGetTexture(material) == nil) + RpMaterialSetTexture(material, gpWhiteTexture); + RpMatFXMaterialSetEffects(material, rpMATFXEFFECTENVMAP); +#ifndef PS2_MATFX + float coef = RpMatFXMaterialGetEnvMapCoefficient(material); + coef *= 0.25f; // Tone down a bit for PC + RpMatFXMaterialSetEnvMapCoefficient(material, coef); +#endif + } + return material; +} + +RpAtomic* +CVehicleModelInfo::SetEnvironmentMapCB(RpAtomic *atomic, void *data) +{ + int fx; + RpGeometry *geo; + + geo = RpAtomicGetGeometry(atomic); + fx = rpMATFXEFFECTNULL; + RpGeometryForAllMaterials(geo, GetMatFXEffectMaterialCB, &fx); + if(fx != rpMATFXEFFECTNULL){ + RpMatFXAtomicEnableEffects(atomic); + RpGeometryForAllMaterials(geo, SetDefaultEnvironmentMapCB, data); + } + return atomic; +} + +void +CVehicleModelInfo::SetEnvironmentMap(void) +{ + CSimpleModelInfo *wheelmi; + int32 i; + + if(pMatFxIdentityFrame == nil){ + RwV3d axis = { 1.0f, 0.0f, 0.0f }; + pMatFxIdentityFrame = RwFrameCreate(); + RwMatrixRotate(RwFrameGetMatrix(pMatFxIdentityFrame), &axis, 60.0f, rwCOMBINEREPLACE); + RwFrameUpdateObjects(pMatFxIdentityFrame); + RwFrameGetLTM(pMatFxIdentityFrame); + } + + RpClumpForAllAtomics(m_clump, SetEnvironmentMapCB, nil); + if(m_wheelId != -1){ + wheelmi = (CSimpleModelInfo*)CModelInfo::GetModelInfo(m_wheelId); + for(i = 0; i < wheelmi->m_numAtomics; i++) + SetEnvironmentMapCB(wheelmi->m_atomics[i], nil); + } + +#ifdef EXTENDED_PIPELINES + CustomPipes::AttachVehiclePipe(m_clump); +#endif +} + +void +CVehicleModelInfo::LoadEnvironmentMaps(void) +{ + int32 txdslot; + + txdslot = CTxdStore::FindTxdSlot("particle"); + CTxdStore::PushCurrentTxd(); + CTxdStore::SetCurrentTxd(txdslot); + if(gpWhiteTexture == nil){ + gpWhiteTexture = RwTextureRead("white", nil); + RwTextureGetName(gpWhiteTexture)[0] = '@'; + RwTextureSetFilterMode(gpWhiteTexture, rwFILTERLINEAR); + } + CTxdStore::PopCurrentTxd(); +} + +void +CVehicleModelInfo::ShutdownEnvironmentMaps(void) +{ + RwTextureDestroy(gpWhiteTexture); + gpWhiteTexture = nil; + RwFrameDestroy(pMatFxIdentityFrame); + pMatFxIdentityFrame = nil; +} + +int +CVehicleModelInfo::GetMaximumNumberOfPassengersFromNumberOfDoors(int id) +{ + int n; + + switch(id){ + case MI_TRAIN: + n = 3; + break; + case MI_FIRETRUCK: + n = 2; + break; + case MI_HUNTER: + n = 1; + break; + default: + n = ((CVehicleModelInfo*)CModelInfo::GetModelInfo(id))->m_numDoors; + } + + if(n == 0) + return id == MI_RCBANDIT || id == MI_PIZZABOY || id == MI_BAGGAGE ? 0 : 1; + + if(id == MI_COACH) + return 8; + + return n - 1; +} |
