1116 lines
35 KiB
C++
1116 lines
35 KiB
C++
#include <iostream>
|
|
#include <nlohmann/json.hpp>
|
|
#include <OgreTerrainGroup.h>
|
|
#include <OgreFileSystemLayer.h>
|
|
#include <OgreRTShaderSystem.h>
|
|
#include <OgreStaticGeometry.h>
|
|
#include <OgreMeshLodGenerator.h>
|
|
#include <Procedural.h>
|
|
#include "Components.h"
|
|
#include "GameData.h"
|
|
#include "TerrainModule.h"
|
|
#include "StaticGeometryModule.h"
|
|
|
|
namespace ECS
|
|
{
|
|
|
|
StaticGeometryModule::StaticGeometryModule(flecs::world &ecs)
|
|
{
|
|
ecs.module<StaticGeometryModule>();
|
|
ecs.component<TerrainSlotParent>();
|
|
ecs.component<TerrainItem>();
|
|
ecs.component<TerrainItemNode>().on_remove(
|
|
[](flecs::entity e, TerrainItemNode &item) {
|
|
if (item.itemNode) {
|
|
item.itemNode->destroyAllChildrenAndObjects();
|
|
item.itemNode->getCreator()->destroySceneNode(
|
|
item.itemNode);
|
|
item.itemNode = nullptr;
|
|
}
|
|
});
|
|
ecs.import <TerrainModule>();
|
|
ecs.observer<const Terrain>("LoadTerrainItems")
|
|
.event(flecs::OnSet)
|
|
.each([](const Terrain &terrain) {
|
|
if (terrain.mTerrainGroup)
|
|
loadItems();
|
|
});
|
|
if (!Ogre::MeshLodGenerator::getSingletonPtr())
|
|
new Ogre::MeshLodGenerator();
|
|
}
|
|
void StaticGeometryModule::addGeometryForSlot(long x, long y)
|
|
{
|
|
std::pair<long, long> slot = { x, y };
|
|
flecs::entity parent =
|
|
ECS::get().query_builder<const TerrainSlotParent>().build().find(
|
|
[&slot](const TerrainSlotParent &parent) {
|
|
return parent.slot == slot;
|
|
});
|
|
std::cout << "addGeometryForSlot: " << x << " " << y << std::endl;
|
|
std::list<flecs::entity> items;
|
|
if (parent.is_valid()) {
|
|
ECS::get()
|
|
.query_builder<const TerrainItem>()
|
|
.with(flecs::ChildOf, parent)
|
|
.without<TerrainItemNode>()
|
|
.write<TerrainItemNode>()
|
|
.build()
|
|
.each([&](flecs::entity e, const TerrainItem &item) {
|
|
std::cout << "item: " << e.id() << std::endl;
|
|
items.push_back(e);
|
|
});
|
|
for (auto e : items) {
|
|
createItemGeometry(e);
|
|
}
|
|
}
|
|
}
|
|
void StaticGeometryModule::removeGeometryForSlot(long x, long y)
|
|
{
|
|
std::pair<long, long> slot = { x, y };
|
|
flecs::entity parent =
|
|
ECS::get().query_builder<const TerrainSlotParent>().build().find(
|
|
[&slot](const TerrainSlotParent &parent) {
|
|
return parent.slot == slot;
|
|
});
|
|
if (parent.is_valid()) {
|
|
ECS::get()
|
|
.query_builder<const TerrainItem>()
|
|
.with(flecs::ChildOf, parent)
|
|
.without<TerrainItemNode>()
|
|
.build()
|
|
.each([](flecs::entity e, const TerrainItem &item) {
|
|
OgreAssert(false, "Implement item geo destroy" +
|
|
item.properties);
|
|
});
|
|
}
|
|
}
|
|
flecs::entity
|
|
StaticGeometryModule::createItem(const Ogre::Vector3 &position,
|
|
const Ogre::Quaternion &orientation,
|
|
const Ogre::String &type)
|
|
{
|
|
long x, y;
|
|
ECS::get<Terrain>().mTerrainGroup->convertWorldPositionToTerrainSlot(
|
|
position, &x, &y);
|
|
std::pair<long, long> pos{ x, y };
|
|
flecs::entity slot =
|
|
ECS::get().query_builder<const TerrainSlotParent>().build().find(
|
|
[&](const TerrainSlotParent &slot) -> bool {
|
|
return slot.slot == pos;
|
|
});
|
|
if (!slot.is_valid())
|
|
slot = ECS::get().entity().set<TerrainSlotParent>({ pos });
|
|
flecs::entity item = ECS::get().entity().child_of(slot);
|
|
nlohmann::json jproperties;
|
|
jproperties["type"] = type;
|
|
item.set<TerrainItem>({ position, orientation, jproperties.dump() });
|
|
std::cout << "createItem: " << x << " " << y << " " << item.id()
|
|
<< std::endl;
|
|
return item;
|
|
}
|
|
void StaticGeometryModule::setItemProperties(flecs::entity id,
|
|
Ogre::String properties)
|
|
{
|
|
OgreAssert(id.is_valid(), "bad id");
|
|
id.get_mut<TerrainItem>().properties = properties;
|
|
id.modified<TerrainItem>();
|
|
}
|
|
const Ogre::String &StaticGeometryModule::getItemProperties(flecs::entity id)
|
|
{
|
|
OgreAssert(id.is_valid(), "bad id");
|
|
return id.get<TerrainItem>().properties;
|
|
}
|
|
static void to_json(nlohmann::json &j, const Ogre::Vector3 &position)
|
|
{
|
|
j["x"] = position.x;
|
|
j["y"] = position.y;
|
|
j["z"] = position.z;
|
|
}
|
|
static void to_json(nlohmann::json &j, const Ogre::Quaternion &orientation)
|
|
{
|
|
j["w"] = orientation.w;
|
|
j["x"] = orientation.x;
|
|
j["y"] = orientation.y;
|
|
j["z"] = orientation.z;
|
|
}
|
|
static void from_json(const nlohmann::json &j, Ogre::Vector3 &position)
|
|
{
|
|
position.x = j["x"].get<float>();
|
|
position.y = j["y"].get<float>();
|
|
position.z = j["z"].get<float>();
|
|
}
|
|
static void from_json(const nlohmann::json &j, Ogre::Quaternion &orientation)
|
|
{
|
|
orientation.w = j["w"].get<float>();
|
|
orientation.x = j["x"].get<float>();
|
|
orientation.y = j["y"].get<float>();
|
|
orientation.z = j["z"].get<float>();
|
|
}
|
|
void StaticGeometryModule::saveItems()
|
|
{
|
|
Ogre::String path = "resources/buildings/items.list";
|
|
if (Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(
|
|
"items.list")) {
|
|
Ogre::String group =
|
|
Ogre::ResourceGroupManager::getSingleton()
|
|
.findGroupContainingResource("items.list");
|
|
Ogre::FileInfoListPtr fileInfoList(
|
|
Ogre::ResourceGroupManager::getSingleton()
|
|
.findResourceFileInfo(group, "items.list"));
|
|
OgreAssert(fileInfoList->size() == 1,
|
|
"worpd_map.png should be there and only once");
|
|
path = fileInfoList->at(0).archive->getName() + "/" +
|
|
"items.list";
|
|
Ogre::FileSystemLayer::removeFile(path);
|
|
}
|
|
std::fstream fout(path.c_str(), std::ios::out);
|
|
nlohmann::json jitemlist;
|
|
ECS::get().query_builder<const TerrainItem>().build().each(
|
|
[&](flecs::entity e, const TerrainItem &item) {
|
|
nlohmann::json jitem;
|
|
to_json(jitem["position"], item.position);
|
|
to_json(jitem["orientation"], item.orientation);
|
|
to_json(jitem["properties"], item.properties);
|
|
jitemlist.push_back(jitem);
|
|
});
|
|
fout << jitemlist.dump();
|
|
fout.close();
|
|
}
|
|
void StaticGeometryModule::loadItems()
|
|
{
|
|
if (!Ogre::ResourceGroupManager::getSingleton().resourceExistsInAnyGroup(
|
|
"items.list"))
|
|
return;
|
|
Ogre::String group = Ogre::ResourceGroupManager::getSingleton()
|
|
.findGroupContainingResource("items.list");
|
|
Ogre::DataStreamPtr stream =
|
|
Ogre::ResourceGroupManager::getSingleton().openResource(
|
|
"items.list", group);
|
|
Ogre::String json = stream->getAsString();
|
|
nlohmann::json jlist = nlohmann::json::parse(json);
|
|
ECS::get().delete_with<TerrainItem>();
|
|
ECS::get().delete_with<TerrainSlotParent>();
|
|
|
|
for (const auto &v : jlist) {
|
|
Ogre::Vector3 position;
|
|
Ogre::Quaternion orientation;
|
|
Ogre::String properties;
|
|
from_json(v["position"], position);
|
|
from_json(v["orientation"], orientation);
|
|
properties = v["properties"].get<Ogre::String>();
|
|
long x, y;
|
|
ECS::get<Terrain>()
|
|
.mTerrainGroup->convertWorldPositionToTerrainSlot(
|
|
position, &x, &y);
|
|
std::pair<long, long> pos{ x, y };
|
|
flecs::entity slot =
|
|
ECS::get()
|
|
.query_builder<const TerrainSlotParent>()
|
|
.build()
|
|
.find([&](const TerrainSlotParent &slot)
|
|
-> bool {
|
|
return slot.slot == pos;
|
|
});
|
|
if (!slot.is_valid())
|
|
slot = ECS::get().entity().set<TerrainSlotParent>(
|
|
{ pos });
|
|
flecs::entity item = ECS::get().entity().child_of(slot);
|
|
item.set<TerrainItem>({ position, orientation, properties });
|
|
std::cout << "createItem: " << x << " " << y << " " << item.id()
|
|
<< std::endl;
|
|
std::cout << "position: " << item.id() << " " << position
|
|
<< std::endl;
|
|
}
|
|
}
|
|
void StaticGeometryModule::getItemPositionPerSlot(
|
|
long x, long y, std::list<Ogre::Vector3> *positions)
|
|
{
|
|
std::pair<long, long> pos{ x, y };
|
|
if (!positions)
|
|
return;
|
|
flecs::entity slot =
|
|
ECS::get().query_builder<const TerrainSlotParent>().build().find(
|
|
[&](const TerrainSlotParent &slot) -> bool {
|
|
return slot.slot == pos;
|
|
});
|
|
if (!slot.is_valid())
|
|
return;
|
|
ECS::get()
|
|
.query_builder<const TerrainItem>()
|
|
.with(flecs::ChildOf, slot)
|
|
.build()
|
|
.each([&](flecs::entity e, const TerrainItem &item) {
|
|
positions->push_back(item.position);
|
|
});
|
|
}
|
|
void StaticGeometryModule::getItemPositions(std::list<Ogre::Vector3> *positions)
|
|
{
|
|
ECS::get().query_builder<const TerrainItem>().build().each(
|
|
[&](flecs::entity e, const TerrainItem &item) {
|
|
positions->push_back(item.position);
|
|
});
|
|
}
|
|
void StaticGeometryModule::getItemPositionAndRotation(
|
|
flecs::entity e, Ogre::Vector3 &position, Ogre::Quaternion &orientation)
|
|
{
|
|
position = e.get<TerrainItem>().position;
|
|
orientation = e.get<TerrainItem>().orientation;
|
|
}
|
|
void StaticGeometryModule::getItemsProperties(
|
|
std::list<std::pair<flecs::entity, Ogre::String> > *items)
|
|
{
|
|
ECS::get().query_builder<const TerrainItem>().build().each(
|
|
[&](flecs::entity e, const TerrainItem &item) {
|
|
items->push_back({ e, item.properties });
|
|
});
|
|
}
|
|
void StaticGeometryModule::createItemGeometry(flecs::entity e)
|
|
{
|
|
OgreAssert(!e.has<TerrainItemNode>(), "Geometry already created");
|
|
Ogre::String props = e.get<TerrainItem>().properties;
|
|
nlohmann::json jp = nlohmann::json::parse(props);
|
|
Ogre::SceneNode *itemNode = ECS::get<EngineData>()
|
|
.mScnMgr->getRootSceneNode()
|
|
->createChildSceneNode();
|
|
itemNode->_setDerivedPosition(e.get<TerrainItem>().position);
|
|
itemNode->_setDerivedOrientation(e.get<TerrainItem>().orientation);
|
|
if (jp.find("staticMesh") != jp.end()) {
|
|
Ogre::String meshName = jp["staticMesh"].get<Ogre::String>();
|
|
Ogre::MeshPtr mesh =
|
|
Ogre::MeshManager::getSingleton().getByName(meshName);
|
|
if (mesh) {
|
|
Ogre::Entity *ent =
|
|
ECS::get<EngineData>().mScnMgr->createEntity(
|
|
mesh);
|
|
itemNode->attachObject(ent);
|
|
}
|
|
} else if (jp.find("type") != jp.end()) {
|
|
Ogre::String itemType = jp["type"].get<Ogre::String>();
|
|
std::cout << "type: " << itemType << std::endl;
|
|
std::cout << "props: " << props << std::endl;
|
|
if (itemType == "harbour") {
|
|
createHarbour(e, itemNode);
|
|
e.set<TerrainItemNode>({ itemNode });
|
|
}
|
|
} else {
|
|
std::cout << "can't build item" << std::endl;
|
|
std::cout << "props: " << props << std::endl;
|
|
OgreAssert(false, "can't create item");
|
|
}
|
|
}
|
|
struct harbourMaker {
|
|
Ogre::Entity *planks, *pillar, *beam;
|
|
harbourMaker(flecs::entity e)
|
|
{
|
|
planks = ECS::get<EngineData>().mScnMgr->createEntity(
|
|
"Plank" + Ogre::StringConverter::toString(e.id()),
|
|
"pier-plank.glb");
|
|
beam = ECS::get<EngineData>().mScnMgr->createEntity(
|
|
"Beam" + Ogre::StringConverter::toString(e.id()),
|
|
"pier-beam.glb");
|
|
pillar = ECS::get<EngineData>().mScnMgr->createEntity(
|
|
"Pillar" + Ogre::StringConverter::toString(e.id()),
|
|
"pier-pillar.glb");
|
|
#if 1
|
|
Ogre::Entity *entities[] = { planks, pillar, beam };
|
|
for (Ogre::Entity *ent : entities) {
|
|
Ogre::MeshPtr mesh = ent->getMesh();
|
|
Ogre::LodConfig config(mesh);
|
|
config.advanced.useCompression = true;
|
|
config.advanced.useVertexNormals = true;
|
|
config.advanced.preventPunchingHoles = true;
|
|
config.advanced.preventBreakingLines = true;
|
|
config.createGeneratedLodLevel(10, 0.15f);
|
|
config.createGeneratedLodLevel(30, 0.25f);
|
|
#if 0
|
|
if (ent == planks)
|
|
config.createManualLodLevel(
|
|
20, "pier-plank-LOD.glb");
|
|
else
|
|
#endif
|
|
config.createGeneratedLodLevel(60, 0.36f);
|
|
config.createGeneratedLodLevel(150, 0.65f);
|
|
// config.createGeneratedLodLevel(20, 0.95);
|
|
config.advanced.useBackgroundQueue = false;
|
|
Ogre::MeshLodGenerator::getSingleton().generateLodLevels(
|
|
config);
|
|
}
|
|
#endif
|
|
}
|
|
};
|
|
struct TiledMeshes {
|
|
struct Tile {
|
|
Ogre::String materialName;
|
|
std::shared_ptr<Ogre::VertexData> vertexData;
|
|
std::shared_ptr<Ogre::IndexData> indexData;
|
|
std::set<uint32_t> positions;
|
|
};
|
|
std::map<Ogre::String, Tile> tiles;
|
|
uint32_t packKey(const Ogre::Vector3i &position)
|
|
{
|
|
uint32_t key = 0;
|
|
key |= (uint32_t)(position[2] + 512) << 20;
|
|
key |= (uint32_t)(position[1] + 512) << 10;
|
|
key |= (uint32_t)(position[0] + 512) << 0;
|
|
return key;
|
|
}
|
|
void unpackKey(uint32_t key, Ogre::Vector3i &position)
|
|
{
|
|
uint32_t mask = 0x3ff;
|
|
position[0] = (int)(key & mask) - 512;
|
|
position[1] = (int)((key >> 10) & mask) - 512;
|
|
position[2] = (int)((key >> 20) & mask) - 512;
|
|
}
|
|
void setTile(const Ogre::String &name, const Ogre::Vector3i &position)
|
|
{
|
|
if (tiles.find(name) == tiles.end())
|
|
return;
|
|
tiles[name].positions.insert(packKey(position));
|
|
}
|
|
void clearTile(const Ogre::String &name, const Ogre::Vector3i &position)
|
|
{
|
|
if (tiles.find(name) == tiles.end())
|
|
return;
|
|
tiles[name].positions.erase(packKey(position));
|
|
#if 0
|
|
auto pos = std::find(tiles[name].positions.begin(),
|
|
tiles[name].positions.end(),
|
|
packKey(position));
|
|
if (pos != tiles[name].positions.end())
|
|
tiles[name].positions.erase(pos);
|
|
#endif
|
|
}
|
|
void addTile(const Ogre::String &name, Ogre::MeshPtr mesh)
|
|
{
|
|
if (mesh->getSubMeshes().size() != 1)
|
|
return;
|
|
Ogre::SubMesh *submesh = mesh->getSubMesh(0);
|
|
Ogre::VertexData *vertexData;
|
|
if (submesh->useSharedVertices)
|
|
vertexData = mesh->sharedVertexData->clone();
|
|
else
|
|
vertexData = submesh->vertexData->clone();
|
|
tiles[name] = { submesh->getMaterialName(),
|
|
std::shared_ptr<Ogre::VertexData>(vertexData),
|
|
std::shared_ptr<Ogre::IndexData>(
|
|
submesh->indexData->clone()),
|
|
{} };
|
|
#if 0
|
|
std::vector<Ogre::Vector3> vertices;
|
|
std::vector<uint32_t> indices;
|
|
int count = mesh->getNumSubMeshes();
|
|
int i, j;
|
|
int indexCount = 0;
|
|
int vertexCount = 0;
|
|
int sharedVertexOffset = 0;
|
|
for (i = 0; i < count; i++) {
|
|
Ogre::SubMesh *submesh = mesh->getSubMesh(i);
|
|
indexCount += submesh->indexData->indexCount;
|
|
if (submesh->useSharedVertices)
|
|
vertexCount +=
|
|
mesh->sharedVertexData->vertexCount;
|
|
else
|
|
vertexCount += submesh->vertexData->vertexCount;
|
|
}
|
|
indices.reserve(indexCount);
|
|
vertices.reserve(vertexCount);
|
|
size_t currentVertexOffset = 0;
|
|
bool added_shared = false;
|
|
for (i = 0; i < count; i++) {
|
|
Ogre::SubMesh *submesh = mesh->getSubMesh(i);
|
|
Ogre::VertexData *vertex_data =
|
|
submesh->useSharedVertices ?
|
|
mesh->sharedVertexData :
|
|
submesh->vertexData;
|
|
bool add_vertices =
|
|
(submesh->useSharedVertices && !added_shared) ||
|
|
!submesh->useSharedVertices;
|
|
if (add_vertices) {
|
|
if (submesh->useSharedVertices)
|
|
sharedVertexOffset = vertices.size();
|
|
const Ogre::VertexDeclaration *decl =
|
|
vertex_data->vertexDeclaration;
|
|
const Ogre::VertexBufferBinding *bind =
|
|
vertex_data->vertexBufferBinding;
|
|
const Ogre::VertexElement *position_element =
|
|
decl->findElementBySemantic(
|
|
Ogre::VES_POSITION);
|
|
if (!position_element)
|
|
continue;
|
|
Ogre::HardwareVertexBufferSharedPtr vbuf =
|
|
bind->getBuffer(
|
|
position_element->getSource());
|
|
unsigned char *vertex_buffer = static_cast<
|
|
unsigned char *>(vbuf->lock(
|
|
Ogre::HardwareBuffer::HBL_READ_ONLY));
|
|
int vertexSize = vbuf->getVertexSize();
|
|
for (j = 0; j < vertex_data->vertexCount; j++) {
|
|
float *position_data;
|
|
position_element
|
|
->baseVertexPointerToElement(
|
|
vertex_buffer,
|
|
&position_data);
|
|
vertices.push_back(
|
|
{ position_data[0],
|
|
position_data[1],
|
|
position_data[2] });
|
|
vertex_buffer += vertexSize;
|
|
}
|
|
if (submesh->useSharedVertices)
|
|
added_shared = true;
|
|
vbuf->unlock();
|
|
}
|
|
Ogre::HardwareIndexBufferSharedPtr ibuf =
|
|
submesh->indexData->indexBuffer;
|
|
size_t numIndices = submesh->indexData->indexCount;
|
|
size_t vertexOffset = submesh->useSharedVertices ?
|
|
sharedVertexOffset :
|
|
currentVertexOffset;
|
|
if (ibuf->getType() ==
|
|
Ogre::HardwareIndexBuffer::IT_32BIT) {
|
|
unsigned int *pIndices = static_cast<
|
|
unsigned int *>(ibuf->lock(
|
|
Ogre::HardwareBuffer::HBL_READ_ONLY));
|
|
for (j = 0; j < numIndices; j++) {
|
|
indices.push_back(
|
|
(uint32_t)pIndices[j] +
|
|
vertexOffset);
|
|
}
|
|
ibuf->unlock();
|
|
} else {
|
|
unsigned short *pIndices = static_cast<
|
|
unsigned short *>(ibuf->lock(
|
|
Ogre::HardwareBuffer::HBL_READ_ONLY));
|
|
for (j = 0; j < numIndices; j++) {
|
|
indices.push_back(
|
|
(uint32_t)pIndices[j] +
|
|
vertexOffset);
|
|
}
|
|
ibuf->unlock();
|
|
}
|
|
currentVertexOffset = vertices.size();
|
|
}
|
|
#endif
|
|
}
|
|
struct buildSettings {
|
|
Ogre::String meshName;
|
|
Ogre::String materialName;
|
|
Ogre::MeshPtr mesh;
|
|
Ogre::SubMesh *sm;
|
|
int vertexCount, vertexOffset;
|
|
int indexCount, indexOffset;
|
|
Ogre::VertexDeclaration *vdecl;
|
|
Ogre::HardwareVertexBufferSharedPtr vbuf;
|
|
Ogre::AxisAlignedBox bounds;
|
|
bool setBounds;
|
|
};
|
|
void configureSettings(struct buildSettings &settings)
|
|
{
|
|
settings.mesh = Ogre::MeshManager::getSingleton().createManual(
|
|
settings.meshName,
|
|
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
|
settings.mesh->createVertexData();
|
|
settings.sm = settings.mesh->createSubMesh();
|
|
settings.vertexCount = 0;
|
|
settings.indexCount = 0;
|
|
settings.vdecl = nullptr;
|
|
for (const auto &tile : tiles) {
|
|
settings.vertexCount +=
|
|
tile.second.vertexData->vertexCount *
|
|
tile.second.positions.size();
|
|
settings.indexCount +=
|
|
tile.second.indexData->indexCount *
|
|
tile.second.positions.size();
|
|
if (!settings.vdecl) {
|
|
settings.vdecl =
|
|
tile.second.vertexData
|
|
->vertexDeclaration->clone();
|
|
settings.materialName =
|
|
tile.second.materialName;
|
|
}
|
|
}
|
|
settings.mesh->sharedVertexData->vertexStart = 0;
|
|
settings.mesh->sharedVertexData->vertexCount =
|
|
settings.vertexCount;
|
|
settings.mesh->sharedVertexData->vertexDeclaration =
|
|
settings.vdecl;
|
|
settings.vbuf =
|
|
Ogre::HardwareBufferManager::getSingleton()
|
|
.createVertexBuffer(
|
|
settings.vdecl->getVertexSize(0),
|
|
settings.vertexCount,
|
|
Ogre::HBU_GPU_ONLY);
|
|
settings.mesh->sharedVertexData->vertexBufferBinding->setBinding(
|
|
0, settings.vbuf);
|
|
settings.sm->indexData->indexStart = 0;
|
|
settings.sm->indexData->indexCount = settings.indexCount;
|
|
settings.sm->indexData->indexBuffer =
|
|
Ogre::HardwareBufferManager::getSingleton()
|
|
.createIndexBuffer(
|
|
Ogre::HardwareIndexBuffer::IT_32BIT,
|
|
settings.sm->indexData->indexCount * 8,
|
|
Ogre::HBU_GPU_ONLY);
|
|
settings.sm->setMaterialName(settings.materialName);
|
|
settings.setBounds = true;
|
|
}
|
|
void processIndex(struct buildSettings &settings,
|
|
const struct Tile &tile, unsigned int *dstIndices)
|
|
{
|
|
int j;
|
|
std::shared_ptr<Ogre::IndexData> srcIndexData = tile.indexData;
|
|
int srcIndexCount = srcIndexData->indexCount;
|
|
std::shared_ptr<Ogre::VertexData> srcVertexData =
|
|
tile.vertexData;
|
|
int srcVertexCount = srcVertexData->vertexCount;
|
|
Ogre::HardwareIndexBufferSharedPtr srcIbuf =
|
|
srcIndexData->indexBuffer;
|
|
Ogre::HardwareBufferLockGuard srcIndexLock(
|
|
srcIbuf, Ogre::HardwareBuffer::HBL_READ_ONLY);
|
|
if (srcIndexData->indexBuffer->getType() ==
|
|
Ogre::HardwareIndexBuffer::IT_32BIT) {
|
|
unsigned int *indices =
|
|
static_cast<unsigned int *>(srcIndexLock.pData);
|
|
for (j = 0; j < srcIndexCount; j++)
|
|
dstIndices[settings.indexOffset + j] =
|
|
indices[j] + settings.vertexOffset;
|
|
} else if (srcIndexData->indexBuffer->getType() ==
|
|
Ogre::HardwareIndexBuffer::IT_16BIT) {
|
|
unsigned short *indices = static_cast<unsigned short *>(
|
|
srcIndexLock.pData);
|
|
for (j = 0; j < srcIndexCount; j++)
|
|
dstIndices[settings.indexOffset + j] =
|
|
indices[j] + settings.vertexOffset;
|
|
}
|
|
}
|
|
void processSingleVertex(
|
|
struct buildSettings &settings,
|
|
const Ogre::VertexDeclaration::VertexElementList &srcElements,
|
|
uint32_t offset, unsigned char *srcData, unsigned char *dstData)
|
|
{
|
|
for (const auto &srcElement : srcElements) {
|
|
unsigned char *srcPtr, *dstPtr;
|
|
const Ogre::VertexElement *destElement =
|
|
settings.vdecl->findElementBySemantic(
|
|
srcElement.getSemantic(),
|
|
srcElement.getIndex());
|
|
if (!destElement)
|
|
goto out;
|
|
if (srcElement.getType() != destElement->getType() ||
|
|
srcElement.getSize() != destElement->getSize())
|
|
goto out;
|
|
srcPtr = srcData + srcElement.getOffset();
|
|
dstPtr = dstData + destElement->getOffset();
|
|
if (destElement->getSemantic() == Ogre::VES_POSITION) {
|
|
float *srcPositionData =
|
|
reinterpret_cast<float *>(srcPtr);
|
|
float *dstPositionData =
|
|
reinterpret_cast<float *>(dstPtr);
|
|
Ogre::Vector3 position(srcPositionData[0],
|
|
srcPositionData[1],
|
|
srcPositionData[2]);
|
|
Ogre::Vector3i offsetv;
|
|
unpackKey(offset, offsetv);
|
|
position.x += (float)offsetv[0];
|
|
position.y += (float)offsetv[1];
|
|
position.z += (float)offsetv[2];
|
|
dstPositionData[0] = position.x;
|
|
dstPositionData[1] = position.y;
|
|
dstPositionData[2] = position.z;
|
|
if (settings.setBounds) {
|
|
settings.bounds.setMinimum(position);
|
|
settings.bounds.setMaximum(position);
|
|
settings.setBounds = false;
|
|
} else
|
|
settings.bounds.merge(position);
|
|
} else if (destElement->getSemantic() ==
|
|
Ogre::VES_NORMAL) {
|
|
float *srcNormalData =
|
|
reinterpret_cast<float *>(srcPtr);
|
|
float *dstNormalData =
|
|
reinterpret_cast<float *>(dstPtr);
|
|
Ogre::Vector3 normal(srcNormalData[0],
|
|
srcNormalData[1],
|
|
srcNormalData[2]);
|
|
dstNormalData[0] = normal.x;
|
|
dstNormalData[1] = normal.y;
|
|
dstNormalData[2] = normal.z;
|
|
} else
|
|
memcpy(dstPtr, srcPtr, srcElement.getSize());
|
|
out:;
|
|
}
|
|
}
|
|
void processTile(struct buildSettings &settings,
|
|
const struct Tile &tile, uint32_t position,
|
|
unsigned char *dstpData)
|
|
{
|
|
std::shared_ptr<Ogre::VertexData> srcVertexData =
|
|
tile.vertexData;
|
|
const Ogre::VertexDeclaration *srcDecl =
|
|
srcVertexData->vertexDeclaration;
|
|
const Ogre::VertexBufferBinding *srcBind =
|
|
srcVertexData->vertexBufferBinding;
|
|
int srcVertexCount = srcVertexData->vertexCount;
|
|
Ogre::HardwareVertexBufferSharedPtr srcVbuf =
|
|
srcBind->getBuffer(0);
|
|
std::shared_ptr<Ogre::IndexData> srcIndexData = tile.indexData;
|
|
int srcIndexCount = srcIndexData->indexCount;
|
|
|
|
Ogre::HardwareBufferLockGuard srcVertexLock(
|
|
srcVbuf, 0, srcVertexCount * srcDecl->getVertexSize(0),
|
|
Ogre::HardwareBuffer::HBL_READ_ONLY);
|
|
const Ogre::VertexDeclaration::VertexElementList &srcElements =
|
|
srcDecl->getElements();
|
|
int j;
|
|
unsigned char *srcpData =
|
|
static_cast<unsigned char *>(srcVertexLock.pData);
|
|
|
|
for (j = 0; j < srcVertexCount; j++) {
|
|
unsigned char *srcData =
|
|
srcpData + j * srcVbuf->getVertexSize();
|
|
unsigned char *dstData =
|
|
dstpData + (settings.vertexOffset +
|
|
j) * settings.vbuf->getVertexSize();
|
|
processSingleVertex(settings, srcElements, position,
|
|
srcData, dstData);
|
|
}
|
|
}
|
|
Ogre::MeshPtr build(const Ogre::String &meshName)
|
|
{
|
|
buildSettings settings;
|
|
settings.meshName = meshName;
|
|
configureSettings(settings);
|
|
{
|
|
Ogre::HardwareBufferLockGuard vertexLock(
|
|
settings.vbuf, 0,
|
|
settings.vertexCount *
|
|
settings.vdecl->getVertexSize(0),
|
|
Ogre::HardwareBuffer::HBL_NO_OVERWRITE);
|
|
Ogre::HardwareBufferLockGuard indexLock(
|
|
settings.sm->indexData->indexBuffer,
|
|
Ogre::HardwareBuffer::HBL_NO_OVERWRITE);
|
|
settings.vertexOffset = 0;
|
|
settings.indexOffset = 0;
|
|
unsigned char *dstpData =
|
|
static_cast<unsigned char *>(vertexLock.pData);
|
|
unsigned int *dstIndices =
|
|
static_cast<unsigned int *>(indexLock.pData);
|
|
|
|
for (const auto &tile : tiles) {
|
|
std::shared_ptr<Ogre::IndexData> srcIndexData =
|
|
tile.second.indexData;
|
|
int srcIndexCount = srcIndexData->indexCount;
|
|
std::shared_ptr<Ogre::VertexData> srcVertexData =
|
|
tile.second.vertexData;
|
|
int srcVertexCount = srcVertexData->vertexCount;
|
|
for (const auto &position :
|
|
tile.second.positions) {
|
|
processTile(settings, tile.second,
|
|
position, dstpData);
|
|
processIndex(settings, tile.second,
|
|
dstIndices);
|
|
settings.vertexOffset += srcVertexCount;
|
|
settings.indexOffset += srcIndexCount;
|
|
Ogre::Vector3i vposition;
|
|
unpackKey(position, vposition);
|
|
std::cout << "position: " << position
|
|
<< " " << vposition
|
|
<< std::endl;
|
|
}
|
|
}
|
|
settings.mesh->_setBounds(settings.bounds);
|
|
}
|
|
Ogre::LodConfig config(settings.mesh);
|
|
// config.advanced.useCompression = false;
|
|
// config.advanced.useVertexNormals = true;
|
|
config.advanced.preventPunchingHoles = true;
|
|
config.advanced.preventBreakingLines = true;
|
|
config.createGeneratedLodLevel(2, 0.15f);
|
|
config.createGeneratedLodLevel(20, 0.49f);
|
|
#if 0
|
|
config.createGeneratedLodLevel(15, 0.49f);
|
|
config.createGeneratedLodLevel(150, 0.75f);
|
|
#endif
|
|
config.advanced.useBackgroundQueue = false;
|
|
Ogre::MeshLodGenerator::getSingleton().generateLodLevels(
|
|
config);
|
|
return settings.mesh;
|
|
}
|
|
void removeTile(const Ogre::String &name)
|
|
{
|
|
tiles.erase(name);
|
|
}
|
|
TiledMeshes()
|
|
{
|
|
}
|
|
};
|
|
void StaticGeometryModule::createHarbour(flecs::entity e,
|
|
Ogre::SceneNode *sceneNode)
|
|
{
|
|
std::cout << "createHarbour " << e.id() << std::endl;
|
|
harbourMaker hm(e);
|
|
Ogre::StaticGeometry *geo =
|
|
ECS::get<EngineData>().mScnMgr->createStaticGeometry(
|
|
"pier_" + Ogre::StringConverter::toString(e.id()));
|
|
geo->setRegionDimensions(Ogre::Vector3(140, 140, 140));
|
|
Ogre::Vector3 geoposition = sceneNode->_getDerivedPosition();
|
|
geoposition.y = 0.0f;
|
|
geo->setOrigin(geoposition);
|
|
#if 1
|
|
Ogre::MaterialPtr pierMaterial;
|
|
pierMaterial = Ogre::MaterialManager::getSingleton().getByName(
|
|
"proceduralMaterialPier" +
|
|
Ogre::StringConverter::toString(e.id()));
|
|
if (!pierMaterial) {
|
|
Procedural::TextureBuffer wood(128);
|
|
Procedural::Colours(&wood)
|
|
.setColourBase(Ogre::ColourValue(0.8f, 0.6f, 0, 1))
|
|
.setColourPercent(Ogre::ColourValue(0.15f, 0.1f, 0, 1))
|
|
.process();
|
|
// Procedural::RectangleTexture woodDraw(&wood);
|
|
Ogre::TexturePtr pierTexture = wood.createTexture(
|
|
"proceduralTexturePier" +
|
|
Ogre::StringConverter::toString(e.id()));
|
|
pierMaterial = Ogre::MaterialManager::getSingletonPtr()->create(
|
|
"proceduralMaterialPier" +
|
|
Ogre::StringConverter::toString(e.id()),
|
|
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME);
|
|
pierMaterial->getTechnique(0)->getPass(0)->setShininess(0);
|
|
pierMaterial->getTechnique(0)->getPass(0)->setDiffuse(
|
|
Ogre::ColourValue::White);
|
|
pierMaterial->getTechnique(0)->getPass(0)->setSpecular(
|
|
Ogre::ColourValue(1.0f, 1.0f, 0.9f));
|
|
pierMaterial->getTechnique(0)
|
|
->getPass(0)
|
|
->createTextureUnitState(
|
|
"proceduralTexturePier" +
|
|
Ogre::StringConverter::toString(e.id()));
|
|
if (Ogre::RTShader::ShaderGenerator::initialize()) {
|
|
pierMaterial->prepare();
|
|
Ogre::RTShader::ShaderGenerator *mShaderGenerator =
|
|
Ogre::RTShader::ShaderGenerator::
|
|
getSingletonPtr();
|
|
mShaderGenerator->createShaderBasedTechnique(
|
|
*pierMaterial,
|
|
Ogre::MaterialManager::DEFAULT_SCHEME_NAME,
|
|
Ogre::RTShader::ShaderGenerator::
|
|
DEFAULT_SCHEME_NAME);
|
|
Ogre::RTShader::RenderState *pMainRenderState =
|
|
mShaderGenerator->getRenderState(
|
|
Ogre::RTShader::ShaderGenerator::
|
|
DEFAULT_SCHEME_NAME,
|
|
*pierMaterial);
|
|
}
|
|
}
|
|
#endif
|
|
|
|
Ogre::Vector3 position = sceneNode->_getDerivedPosition();
|
|
Ogre::String props = e.get<TerrainItem>().properties;
|
|
nlohmann::json jp = nlohmann::json::parse(props);
|
|
float pierHeight = 0.0f, pierOffset = 0.0f, pierLength = 6.0f,
|
|
pierDepth = 6.0f;
|
|
if (jp.find("pierOffset") != jp.end())
|
|
pierOffset = jp["pierOffset"].get<float>();
|
|
if (jp.find("pierLength") != jp.end())
|
|
pierLength = jp["pierLength"].get<float>();
|
|
if (jp.find("pierDepth") != jp.end())
|
|
pierDepth = jp["pierDepth"].get<float>();
|
|
if (jp.find("pierHeight") != jp.end())
|
|
pierHeight = jp["pierHeight"].get<float>();
|
|
Procedural::TriangleBuffer tb;
|
|
float plankLength = 2.0f;
|
|
float plankWidth = 4.01f;
|
|
const float beamLength = 6.0f;
|
|
const float beamWidth = 5.5f;
|
|
if (pierLength < 12.0f)
|
|
pierLength = 12.0f;
|
|
auto processGrid = [&sceneNode, &geo](float stepLength, float length,
|
|
float zoffset, float xofft,
|
|
Ogre::Entity *ent) {
|
|
float step = 0.0f;
|
|
while (step < length) {
|
|
Ogre::Vector3 worldPosition =
|
|
sceneNode->_getDerivedPosition() +
|
|
sceneNode->_getDerivedOrientation() *
|
|
Ogre::Vector3::UNIT_Z *
|
|
(step + zoffset);
|
|
Ogre::Quaternion worldOrientation =
|
|
sceneNode->_getDerivedOrientation();
|
|
Ogre::Vector3 xoffset = worldOrientation *
|
|
(Ogre::Vector3::UNIT_X * xofft);
|
|
geo->addEntity(ent, worldPosition + xoffset,
|
|
worldOrientation,
|
|
Ogre::Vector3(1, 1, 1));
|
|
step += stepLength;
|
|
}
|
|
};
|
|
float xofftPlanks;
|
|
for (xofftPlanks = -plankWidth; xofftPlanks <= plankWidth;
|
|
xofftPlanks += plankWidth)
|
|
processGrid(plankLength, pierLength,
|
|
pierOffset + plankLength / 2.0f, xofftPlanks,
|
|
hm.planks);
|
|
{
|
|
float step = 0.0f;
|
|
while (step < pierLength) {
|
|
// pillars
|
|
Procedural::BoxGenerator()
|
|
.setSizeX(0.5f)
|
|
.setSizeY(pierDepth)
|
|
.setSizeZ(0.5f)
|
|
.setEnableNormals(true)
|
|
.setTextureRectangle(
|
|
Ogre::RealRect(0.2f, 0.0f, 0.1f, 0.1f))
|
|
.setPosition(Ogre::Vector3(
|
|
-5.0f, -pierDepth / 2.0f + 0.5f, step))
|
|
.addToTriangleBuffer(tb);
|
|
Procedural::BoxGenerator()
|
|
.setSizeX(0.5f)
|
|
.setSizeY(pierDepth)
|
|
.setSizeZ(0.5f)
|
|
.setEnableNormals(true)
|
|
.setTextureRectangle(
|
|
Ogre::RealRect(0.2f, 0.0f, 0.1f, 0.1f))
|
|
.setPosition(Ogre::Vector3(
|
|
5.0f, -pierDepth / 2.0f + 0.5f, step))
|
|
.addToTriangleBuffer(tb);
|
|
step += 6.0f;
|
|
}
|
|
step = pierLength - 0.5f;
|
|
while (step >= 0.0f) {
|
|
// bollards
|
|
Procedural::CylinderGenerator()
|
|
.setHeight(0.8f)
|
|
.setRadius(0.3f)
|
|
.setTextureRectangle(
|
|
Ogre::RealRect(0.2f, 0.0f, 0.1f, 0.1f))
|
|
.setPosition(Ogre::Vector3(
|
|
-5.3f, 0.4f + 0.5f + 0.1f, step))
|
|
.addToTriangleBuffer(tb);
|
|
Procedural::CylinderGenerator()
|
|
.setHeight(0.8f)
|
|
.setRadius(0.3f)
|
|
.setTextureRectangle(
|
|
Ogre::RealRect(0.2f, 0.0f, 0.1f, 0.1f))
|
|
.setPosition(Ogre::Vector3(
|
|
5.3f, 0.4f + 0.5f + 0.1f, step))
|
|
.addToTriangleBuffer(tb);
|
|
step -= 12.0f;
|
|
}
|
|
// beams
|
|
float beamHeight = 0.3f;
|
|
Procedural::BoxGenerator()
|
|
.setSizeX(0.5f)
|
|
.setSizeY(beamHeight)
|
|
.setSizeZ(pierLength)
|
|
.setEnableNormals(true)
|
|
.setTextureRectangle(
|
|
Ogre::RealRect(0.2f, 0.0f, 0.1f, 0.1f))
|
|
.setPosition(Ogre::Vector3(-5.0f,
|
|
0.2 + beamHeight / 2.0f,
|
|
pierLength / 2.0f))
|
|
.addToTriangleBuffer(tb);
|
|
Procedural::BoxGenerator()
|
|
.setSizeX(0.5f)
|
|
.setSizeY(beamHeight)
|
|
.setSizeZ(pierLength)
|
|
.setEnableNormals(true)
|
|
.setTextureRectangle(
|
|
Ogre::RealRect(0.2f, 0.0f, 0.1f, 0.1f))
|
|
.setPosition(Ogre::Vector3(5.0f,
|
|
0.2 + beamHeight / 2.0f,
|
|
pierLength / 2.0f))
|
|
.addToTriangleBuffer(tb);
|
|
}
|
|
Ogre::String meshName =
|
|
"pier" + Ogre::StringConverter::toString(e.id());
|
|
{
|
|
Ogre::MeshPtr mesh = tb.transformToMesh(meshName);
|
|
Ogre::LodConfig config(mesh);
|
|
// config.advanced.useCompression = false;
|
|
// config.advanced.useVertexNormals = true;
|
|
config.advanced.preventPunchingHoles = true;
|
|
config.advanced.preventBreakingLines = true;
|
|
config.createGeneratedLodLevel(10, 0.15f);
|
|
config.createGeneratedLodLevel(30, 0.25f);
|
|
config.createGeneratedLodLevel(60, 0.36f);
|
|
config.createGeneratedLodLevel(150, 0.65f);
|
|
config.advanced.useBackgroundQueue = false;
|
|
Ogre::MeshLodGenerator::getSingleton().generateLodLevels(
|
|
config);
|
|
Ogre::Entity *ent =
|
|
ECS::get<EngineData>().mScnMgr->createEntity(mesh);
|
|
Ogre::SceneNode *pierNode = sceneNode->createChildSceneNode();
|
|
float xofft = 0.0f;
|
|
Ogre::Vector3 worldPosition =
|
|
sceneNode->_getDerivedPosition() +
|
|
sceneNode->_getDerivedOrientation() *
|
|
Ogre::Vector3::UNIT_Z * (pierOffset);
|
|
worldPosition.y = 0.0f;
|
|
Ogre::Quaternion worldOrientation =
|
|
sceneNode->_getDerivedOrientation();
|
|
Ogre::Vector3 xoffset =
|
|
worldOrientation * (Ogre::Vector3::UNIT_X * xofft);
|
|
pierNode->_setDerivedPosition(worldPosition + xoffset);
|
|
ent->setMaterial(pierMaterial);
|
|
//pierNode->attachObject(ent);
|
|
geo->addEntity(ent, worldPosition + xoffset, worldOrientation,
|
|
Ogre::Vector3(1, 1, 1));
|
|
}
|
|
geo->build();
|
|
std::cout << meshName << std::endl;
|
|
|
|
#if 0
|
|
float step = 0.0f;
|
|
float h = Ogre::Math::Sin(step + position.z * 60.0f +
|
|
position.x * 60.0f * 60.0f) *
|
|
0.1f;
|
|
if (pierLength < 12.0f)
|
|
pierLength = 12.0f;
|
|
if (pierHeight > 0.0f) {
|
|
Procedural::BoxGenerator()
|
|
.setSizeX(10.0f)
|
|
.setSizeY(0.5f)
|
|
.setSizeZ(pierHeight)
|
|
.setOrientation(Ogre::Quaternion(
|
|
Ogre::Degree(-45), Ogre::Vector3(1, 0, 0)))
|
|
.setTextureRectangle(
|
|
Ogre::RealRect(0.0f, 0.0f, 0.1f, 0.1f))
|
|
.setPosition(Ogre::Vector3(
|
|
0.0f,
|
|
pierHeight + 0.5f -
|
|
pierHeight *
|
|
Ogre::Math::Sin(
|
|
Ogre::Degree(45)) /
|
|
2.0f,
|
|
-pierHeight / 2.0f *
|
|
Ogre::Math::Cos(Ogre::Degree(45))))
|
|
.addToTriangleBuffer(tb);
|
|
}
|
|
while (step < pierOffset - 2.0f) {
|
|
Procedural::BoxGenerator()
|
|
.setSizeX(10.0f)
|
|
.setSizeY(0.4f)
|
|
.setSizeZ(0.8f)
|
|
.setTextureRectangle(
|
|
Ogre::RealRect(0.1f, 0.0f, 0.1f, 0.1f))
|
|
.setPosition(Ogre::Vector3(0.0f, 0.5f + h + pierHeight,
|
|
step))
|
|
.addToTriangleBuffer(tb);
|
|
h = Ogre::Math::Sin(step + position.z * 60.0f +
|
|
position.x * 60.0f * 60.0f) *
|
|
0.1f;
|
|
step += 1.0f;
|
|
}
|
|
step = 0.0f;
|
|
while (step < pierLength) {
|
|
h = Ogre::Math::Sin(step + pierOffset + position.z * 60.0f +
|
|
position.x * 60.0f * 60.0f) *
|
|
0.1f;
|
|
// pillars
|
|
Procedural::BoxGenerator()
|
|
.setSizeX(0.5f)
|
|
.setSizeY(pierDepth)
|
|
.setSizeZ(0.5f)
|
|
.setEnableNormals(true)
|
|
.setTextureRectangle(
|
|
Ogre::RealRect(0.2f, 0.0f, 0.1f, 0.1f))
|
|
.setPosition(Ogre::Vector3(
|
|
-4.0f, -position.y - pierDepth / 2.0f + 0.5f,
|
|
step + pierOffset))
|
|
.addToTriangleBuffer(tb);
|
|
Procedural::BoxGenerator()
|
|
.setSizeX(0.5f)
|
|
.setSizeY(pierDepth)
|
|
.setSizeZ(0.5f)
|
|
.setEnableNormals(true)
|
|
.setTextureRectangle(
|
|
Ogre::RealRect(0.2f, 0.0f, 0.1f, 0.1f))
|
|
.setPosition(Ogre::Vector3(
|
|
4.0f, -position.y - pierDepth / 2.0f + 0.5f,
|
|
step + pierOffset))
|
|
.addToTriangleBuffer(tb);
|
|
step += 6.0f;
|
|
}
|
|
step = 0.0f;
|
|
#endif
|
|
#if 0
|
|
while (step < pierLength) {
|
|
h = Ogre::Math::Sin(step + pierOffset + position.z * 60.0f +
|
|
position.x * 60.0f * 60.0f) *
|
|
0.01f;
|
|
Ogre::Vector3 worldPosition =
|
|
sceneNode->_getDerivedPosition() +
|
|
sceneNode->_getDerivedOrientation() *
|
|
Ogre::Vector3::UNIT_Z *
|
|
(step + pierOffset + plankLength / 2.0f);
|
|
Ogre::Quaternion worldOrientation =
|
|
sceneNode->_getDerivedOrientation();
|
|
float xofft;
|
|
for (xofft = -plankWidth - plankLength / 2.0f;
|
|
xofft <= plankWidth + plankWidth / 2.0f;
|
|
xofft += plankWidth) {
|
|
Ogre::Vector3 xoffset = worldOrientation *
|
|
(Ogre::Vector3::UNIT_X * xofft);
|
|
geo->addEntity(planks, worldPosition + xoffset,
|
|
worldOrientation,
|
|
Ogre::Vector3(1, 1, 1));
|
|
}
|
|
step += plankLength;
|
|
}
|
|
#endif
|
|
#if 0
|
|
float xofftBeam;
|
|
for (xofftBeam = -beamWidth; xofftBeam <= beamWidth;
|
|
xofftBeam += beamWidth)
|
|
processGrid(beamLength, pierLength,
|
|
pierOffset + beamLength / 2.0f, xofftBeam, hm.beam);
|
|
#endif
|
|
#if 0
|
|
step = 0.0f;
|
|
while (step < pierLength) {
|
|
h = Ogre::Math::Sin(step + pierOffset + position.z * 60.0f +
|
|
position.x * 60.0f * 60.0f) *
|
|
0.01f;
|
|
Ogre::Vector3 worldPosition =
|
|
sceneNode->_getDerivedPosition() +
|
|
sceneNode->_getDerivedOrientation() *
|
|
Ogre::Vector3::UNIT_Z *
|
|
(step + pierOffset + beamLength / 2.0f);
|
|
Ogre::Quaternion worldOrientation =
|
|
sceneNode->_getDerivedOrientation();
|
|
float xofft;
|
|
for (xofft = -beamWidth - beamWidth / 2.0f;
|
|
xofft <= beamWidth + beamWidth / 2.0f;
|
|
xofft += beamWidth) {
|
|
Ogre::Vector3 xoffset = worldOrientation *
|
|
(Ogre::Vector3::UNIT_X * xofft);
|
|
geo->addEntity(beam, worldPosition + xoffset,
|
|
worldOrientation,
|
|
Ogre::Vector3(1, 1, 1));
|
|
}
|
|
step += beamLength;
|
|
}
|
|
#endif
|
|
#if 0
|
|
Procedural::BoxGenerator()
|
|
.setSizeX(0.5f)
|
|
.setSizeY(0.5f)
|
|
.setSizeZ(pierLength)
|
|
.setTextureRectangle(Ogre::RealRect(0.4f, 0.0f, 0.1f, 0.1f))
|
|
.setEnableNormals(true)
|
|
.setPosition(Ogre::Vector3(-4.0f, -position.y + 0.5f,
|
|
pierOffset + pierLength / 2.0f))
|
|
.addToTriangleBuffer(tb);
|
|
Procedural::BoxGenerator()
|
|
.setSizeX(0.5f)
|
|
.setSizeY(0.5f)
|
|
.setSizeZ(pierLength)
|
|
.setTextureRectangle(Ogre::RealRect(0.4f, 0.0f, 0.1f, 0.1f))
|
|
.setEnableNormals(true)
|
|
.setPosition(Ogre::Vector3(4.0f, -position.y + 0.5f,
|
|
pierOffset + pierLength / 2.0f))
|
|
.addToTriangleBuffer(tb);
|
|
#endif
|
|
}
|
|
}
|