/* * Method: Number * * Generates a real (non-integer) number. * * > number = rand:Number() * > number = rand:Number(max) * > number = rand:Number(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_number(lua_State *l) { MTRand *rand = LuaObject<MTRand>::CheckFromLua(1); double min, max; if (lua_isnumber(l, 2) && lua_isnumber(l, 3)) { min = lua_tonumber(l, 2); max = lua_tonumber(l, 3); } else if (lua_isnumber(l, 2)) { min = 0.0; max = lua_tonumber(l, 2); } else { lua_pushnumber(l, rand->Double()); return 1; } if (min > max) luaL_error(l, "Max must be bigger than min in random number range"); lua_pushnumber(l, rand->Double(min, max)); return 1; }
void GenCol(float col[4], MTRand &rng) const { float ma = 1 + float(rng.Double(modAll*2)-modAll); for (int i=0; i<4; i++) col[i] = baseCol[i] + float(rng.Double(-modCol[i], modCol[i])); for (int i=0; i<3; i++) col[i] = Clamp(ma*col[i], 0.0f, 1.0f); }
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); } }