Example #1
0
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);
	}
}
Example #2
0
heap::heap(live_heap &&h)
{
    assert(h.is_contiguous());
    log_debug("freezing heap with ID %d, %d item pointers, %d bytes payload",
              h.get_cnt(), h.pointers.size(), h.min_length);
    /* The length of addressed items is measured from the item to the
     * address of the next item, or the end of the heap. We may receive
     * packets (and hence pointers) out-of-order, so we have to sort.
     * The mask preserves both the address and the immediate-mode flag,
     * so that all addressed items sort together.
     *
     * The sort needs to be stable, because there can be zero-length fields.
     * TODO: these can still break if they cross packet boundaries.
     */
    item_pointer_t sort_mask =
        immediate_mask | ((item_pointer_t(1) << h.heap_address_bits) - 1);
    auto compare = [sort_mask](item_pointer_t a, item_pointer_t b) {
        return (a & sort_mask) < (b & sort_mask);
    };
    std::stable_sort(h.pointers.begin(), h.pointers.end(), compare);

    pointer_decoder decoder(h.heap_address_bits);
    // Determine how much memory is needed to store immediates
    std::size_t n_immediates = 0;
    for (std::size_t i = 0; i < h.pointers.size(); i++)
    {
        item_pointer_t pointer = h.pointers[i];
        if (decoder.is_immediate(pointer))
            n_immediates++;
    }
    // Allocate memory
    const std::size_t immediate_size = h.heap_address_bits / 8;
    const std::size_t id_size = sizeof(item_pointer_t) - immediate_size;
    if (n_immediates > 0)
        immediate_payload.reset(new uint8_t[immediate_size * n_immediates]);
    uint8_t *next_immediate = immediate_payload.get();
    items.reserve(h.pointers.size());

    for (std::size_t i = 0; i < h.pointers.size(); i++)
    {
        item new_item;
        item_pointer_t pointer = h.pointers[i];
        new_item.id = decoder.get_id(pointer);
        if (new_item.id == 0)
            continue; // just padding
        new_item.is_immediate = decoder.is_immediate(pointer);
        if (new_item.is_immediate)
        {
            new_item.ptr = next_immediate;
            new_item.length = immediate_size;
            item_pointer_t pointer_be = htobe<item_pointer_t>(pointer);
            std::memcpy(
                next_immediate,
                reinterpret_cast<const std::uint8_t *>(&pointer_be) + id_size,
                immediate_size);
            log_debug("Found new immediate item ID %d, value %d",
                      new_item.id, decoder.get_immediate(pointer));
            next_immediate += immediate_size;
        }
        else
        {
            s_item_pointer_t start = decoder.get_address(pointer);
            s_item_pointer_t end;
            if (i + 1 < h.pointers.size()
                && !decoder.is_immediate(h.pointers[i + 1]))
                end = decoder.get_address(h.pointers[i + 1]);
            else
                end = h.min_length;
            if (start == end)
            {
                log_debug("skipping empty item %d", new_item.id);
                continue;
            }
            new_item.ptr = h.payload.get() + start;
            new_item.length = end - start;
            log_debug("found new addressed item ID %d, offset %d, length %d",
                      new_item.id, start, end - start);
        }
        items.push_back(new_item);
    }
    cnt = h.cnt;
    flavour_ = flavour(maximum_version, 8 * sizeof(item_pointer_t),
                       h.heap_address_bits, h.bug_compat);
    payload = std::move(h.payload);
    // Reset h so that it still satisfies its invariants
    h = live_heap(0, h.bug_compat);
}