void ModelBody::RebuildCollisionMesh() { if (m_geom) { if (GetFrame()) RemoveGeomsFromFrame(GetFrame()); DeleteGeoms(); } m_collMesh = m_model->GetCollisionMesh(); SetPhysRadius(m_collMesh->GetAabb().GetRadius()); //static geom m_geom = new Geom(m_collMesh->GetGeomTree()); m_geom->SetUserData(static_cast<void*>(this)); m_geom->MoveTo(GetOrient(), GetPosition()); //have to figure out which collision geometries are responsible for which geomtrees DynGeomFinder dgf; m_model->GetRoot()->Accept(dgf); //dynamic geoms for (auto it = m_collMesh->GetDynGeomTrees().begin(); it != m_collMesh->GetDynGeomTrees().end(); ++it) { Geom *dynG = new Geom(*it); dynG->SetUserData(static_cast<void*>(this)); dynG->MoveTo(GetOrient(), GetPosition()); dynG->m_animTransform = matrix4x4d::Identity(); SceneGraph::CollisionGeometry *cg = dgf.GetCgForTree(*it); if (cg) cg->SetGeom(dynG); m_dynGeoms.push_back(dynG); } if (GetFrame()) AddGeomsToFrame(GetFrame()); }
void CityOnPlanet::PutCityBit(MTRand &rand, const matrix4x4d &rot, vector3d p1, vector3d p2, vector3d p3, vector3d p4) { double rad = (p1-p2).Length()*0.5; LmrModel *model(0); double modelRadXZ(0); const LmrCollMesh *cmesh(0); vector3d cent = (p1+p2+p3+p4)*0.25; cityflavourdef_t *flavour(0); citybuildinglist_t *buildings(0); // pick a building flavour (city, windfarm, etc) for (int flv=0; flv<CITYFLAVOURS; flv++) { flavour = &cityflavour[flv]; buildings = &s_buildingLists[flavour->buildingListIdx]; int tries; for (tries=20; tries--; ) { const citybuilding_t &bt = buildings->buildings[rand.Int32(buildings->numBuildings)]; model = bt.resolvedModel; modelRadXZ = bt.xzradius; cmesh = bt.collMesh; if (modelRadXZ < rad) break; if (tries == 0) return; } bool tooDistant = ((flavour->center - cent).Length()*(1.0/flavour->size) > rand.Double()); if (!tooDistant) break; else flavour = 0; } if (flavour == 0) { if (rad > MIN_SEG_SIZE) goto always_divide; else return; } if (rad > modelRadXZ*2.0) { always_divide: vector3d a = (p1+p2)*0.5; vector3d b = (p2+p3)*0.5; vector3d c = (p3+p4)*0.5; vector3d d = (p4+p1)*0.5; vector3d e = (p1+p2+p3+p4)*0.25; PutCityBit(rand, rot, p1, a, e, d); PutCityBit(rand, rot, a, p2, b, e); PutCityBit(rand, rot, e, b, p3, c); PutCityBit(rand, rot, d, e, c, p4); } else { cent = cent.Normalized(); double height = m_planet->GetTerrainHeight(cent); /* don't position below sealevel! */ if (height - m_planet->GetSBody()->GetRadius() <= 0.0) return; cent = cent * height; assert(cmesh); Geom *geom = new Geom(cmesh->geomTree); int rotTimes90 = rand.Int32(4); matrix4x4d grot = rot * matrix4x4d::RotateYMatrix(M_PI*0.5*double(rotTimes90)); geom->MoveTo(grot, cent); geom->SetUserData(this); // f->AddStaticGeom(geom); BuildingDef def = { model, cmesh->GetBoundingRadius(), rotTimes90, cent, geom, false }; m_buildings.push_back(def); } }