void SpaceStation::Render(const vector3d &viewCoords, const matrix4x4d &viewTransform) { /* Well this is nice... */ static int poo=0; if (!poo) { poo = 1; LmrGetModelsWithTag("advert", s_advertModels); } // it is silly to do this every render call // // random advert models in pFlag[16 .. 19] // station name in pText[0] // docking port in pText[1] MTRand rand; rand.seed(m_sbody->seed); LmrObjParams ¶ms = GetLmrObjParams(); /* random advert models */ params.argStrings[4] = s_advertModels[rand.Int32(s_advertModels.size())]->GetName(); params.argStrings[5] = s_advertModels[rand.Int32(s_advertModels.size())]->GetName(); params.argStrings[6] = s_advertModels[rand.Int32(s_advertModels.size())]->GetName(); params.argStrings[7] = s_advertModels[rand.Int32(s_advertModels.size())]->GetName(); params.argStrings[0] = GetLabel().c_str(); SetLmrTimeParams(); for (int i=0; i<MAX_DOCKING_PORTS; i++) { params.argDoubles[ARG_STATION_BAY1_STAGE + i] = double(m_shipDocking[i].stage); params.argDoubles[ARG_STATION_BAY1_POS + i] = m_shipDocking[i].stagePos; } RenderLmrModel(viewCoords, viewTransform); /* don't render city if too far away */ if (viewCoords.Length() > 1000000.0) return; // find planet Body* Planet *planet; { Body *_planet = GetFrame()->m_astroBody; if ((!_planet) || !_planet->IsType(Object::PLANET)) { // orbital spaceport -- don't make city turds } else { planet = static_cast<Planet*>(_planet); if (!m_adjacentCity) { m_adjacentCity = new CityOnPlanet(planet, this, m_sbody->seed); } m_adjacentCity->Render(this, viewCoords, viewTransform); } } }
/* * Method: Integer * * Generates an integer number * * > number = rand:Integer() * > number = rand:Integer(max) * > number = rand:Integer(min, max) * * Parameters: * * min - optional, the minimum possible value for the generated number. If * omitted, defaults to 0 * * max - optional, the maximum possible value for the generated number. If * omitted, defaults to a very large number (currently 2^32-1) * * Return: * * number - the random number * * Availability: * * alpha 10 * * Status: * * stable */ static int l_rand_integer(lua_State *l) { MTRand *rand = LuaObject<MTRand>::CheckFromLua(1); int min, max; if (lua_isnumber(l, 2) && lua_isnumber(l, 3)) { min = lua_tointeger(l, 2); max = lua_tointeger(l, 3); } else if (lua_isnumber(l, 2)) { min = 0; max = lua_tointeger(l, 2); } else { lua_pushnumber(l, rand->Int32()); return 1; } if (min > max) luaL_error(l, "Max must be bigger than min in random number range"); lua_pushnumber(l, rand->Int32(min, max)); return 1; }
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); } }
CityOnPlanet::CityOnPlanet(Planet *planet, SpaceStation *station, Uint32 seed) { m_buildings.clear(); m_planet = planet; m_frame = planet->GetFrame(); m_detailLevel = Pi::detail.cities; /* Resolve city model numbers since it is a bit expensive */ if (!s_cityBuildingsInitted) { s_cityBuildingsInitted = true; for (int i=0; i<MAX_BUILDING_LISTS; i++) { lookupBuildingListModels(&s_buildingLists[i]); } } Aabb aabb; station->GetAabb(aabb); matrix4x4d m; station->GetRotMatrix(m); vector3d mx = m*vector3d(1,0,0); vector3d mz = m*vector3d(0,0,1); MTRand rand; rand.seed(seed); vector3d p = station->GetPosition(); vector3d p1, p2, p3, p4; double sizex = START_SEG_SIZE;// + rand.Int32((int)START_SEG_SIZE); double sizez = START_SEG_SIZE;// + rand.Int32((int)START_SEG_SIZE); // always have random shipyard buildings around the space station cityflavour[0].buildingListIdx = 0;//2; cityflavour[0].center = p; cityflavour[0].size = 500; for (int i=1; i<CITYFLAVOURS; i++) { cityflavour[i].buildingListIdx = MAX_BUILDING_LISTS>1 ? rand.Int32(MAX_BUILDING_LISTS-1) : 0; citybuildinglist_t *blist = &s_buildingLists[cityflavour[i].buildingListIdx]; double a = rand.Int32(-1000,1000); double b = rand.Int32(-1000,1000); cityflavour[i].center = p + a*mx + b*mz; cityflavour[i].size = rand.Int32(int(blist->minRadius), int(blist->maxRadius)); } for (int side=0; side<4; side++) { /* put buildings on all sides of spaceport */ switch(side) { case 3: p1 = p + mx*(aabb.min.x) + mz*aabb.min.z; p2 = p + mx*(aabb.min.x) + mz*(aabb.min.z-sizez); p3 = p + mx*(aabb.min.x+sizex) + mz*(aabb.min.z-sizez); p4 = p + mx*(aabb.min.x+sizex) + mz*(aabb.min.z); break; case 2: p1 = p + mx*(aabb.min.x-sizex) + mz*aabb.max.z; p2 = p + mx*(aabb.min.x-sizex) + mz*(aabb.max.z-sizez); p3 = p + mx*(aabb.min.x) + mz*(aabb.max.z-sizez); p4 = p + mx*(aabb.min.x) + mz*(aabb.max.z); break; case 1: p1 = p + mx*(aabb.max.x-sizex) + mz*aabb.max.z; p2 = p + mx*(aabb.max.x) + mz*aabb.max.z; p3 = p + mx*(aabb.max.x) + mz*(aabb.max.z+sizez); p4 = p + mx*(aabb.max.x-sizex) + mz*(aabb.max.z+sizez); break; default: case 0: p1 = p + mx*aabb.max.x + mz*aabb.min.z; p2 = p + mx*(aabb.max.x+sizex) + mz*aabb.min.z; p3 = p + mx*(aabb.max.x+sizex) + mz*(aabb.min.z+sizez); p4 = p + mx*aabb.max.x + mz*(aabb.min.z+sizez); break; } PutCityBit(rand, m, p1, p2, p3, p4); } AddStaticGeomsToCollisionSpace(); }