#include "region.h" #include "../../ext.h" #include "generator.h" #include "../light/light.h" void ext::Region::initialize() { ext::Object::initialize(); this->addComponent>(); this->addComponent(); this->m_name = "Region"; this->load(); } void ext::Region::tick() { uf::Entity::tick(); } void ext::Region::load() { uf::Mesh& mesh = this->getComponent(); ext::TerrainGenerator& generator = this->getComponent(); uf::Serializer& metadata = this->getComponent(); if ( metadata["region"]["initialized"].asBool() ) return; pod::Vector3ui size; { size.x = metadata["region"]["size"][0].asUInt(); size.y = metadata["region"]["size"][1].asUInt(); size.z = metadata["region"]["size"][2].asUInt(); } /* Metadata */ { metadata["region"]["modified"] = true; metadata["region"]["initialized"] = true; metadata["region"]["rasterized"] = false; } generator.initialize(size); generator.generate(*this); /* Collider */ { pod::Transform<>& transform = this->getComponent>(); uf::CollisionBody& collider = this->getComponent(); auto*** voxels = generator.getVoxels(); for ( uint x = 0; x < size.x; ++x ) { for ( uint y = 0; y < size.y; ++y ) { for ( uint z = 0; z < size.z; ++z ) { pod::Vector3 offset = transform.position; offset.x += x - (size.x / 2.0f); offset.y += y - (size.y / 2.0f); offset.z += z - (size.z / 2.0f); ext::TerrainVoxel voxel = ext::TerrainVoxel::atlas(voxels[x][y][z]); if ( !voxel.opaque() ) continue; uf::Collider* box = new uf::AABBox( offset, {0.5, 0.5, 0.5} ); collider.add(box); } } } } if ( this->getComponent>().position.y < 0 ) { float r = (rand() % 100) / 100.0; bool addLight = r < metadata["region"]["light"]["random"].asFloat(); static bool first = false; if ( !first ) addLight = first = true; // Guarantee at least one light source (per XZ plane) if ( false && !addLight ) { addLight = true; ext::Terrain& parent = this->getParent(); for ( const uf::Entity* pRegion : parent.getChildren() ) if ( pRegion->getName() == "Region" ) { const pod::Transform<>& tRegion = pRegion->getComponent>(); const pod::Transform<>& transform = this->getComponent>(); if ( tRegion.position.y != transform.position.y ) continue; for ( const uf::Entity* pLight : pRegion->getChildren() ) if ( pLight->getName() == "Light" ) { addLight = false; break; } if ( !addLight ) break; } } if ( addLight ) { pod::Vector3 color = { 1.0, 1.0, 1.0 }; { float r = (rand() % 256) / 256.0; color.x -= r; float g = (rand() % 256) / 256.0; color.y -= g; float b = (rand() % 256) / 256.0; color.z -= b; color = uf::vector::normalize( color ); } int radius = metadata["region"]["light"]["radius"].asInt(); for ( int i = 0; i < radius; ++i ) { uf::Entity* entity = new ext::Light; if ( !((ext::Object*) entity)->load("./light/config.json") ) { uf::iostream << "Error loading `" << "./light/config.json" << "!" << "\n"; delete entity; return; } this->addChild(*entity); entity->initialize(); pod::Transform<>& parent = this->getComponent>(); pod::Transform<>& transform = entity->getComponent>();//entity->getComponent().getTransform(); entity->getComponent().getTransform().reference = &transform; transform = uf::transform::initialize( transform ); transform.position = parent.position; uf::transform::rotate( transform, transform.up, (360.0 / radius) * (3.1415926/180.0) * i ); entity->getComponent().update(true); // ((ext::Light*)entity)->setColor( color ); uf::Serializer& lMetadata = entity->getComponent(); lMetadata["light"]["color"][0] = color.x; lMetadata["light"]["color"][1] = color.y; lMetadata["light"]["color"][2] = color.z; } /* Down */ if ( metadata["region"]["light"]["down"].asBool() ) { uf::Entity* entity = new ext::Light; if ( !((ext::Object*) entity)->load("./light/config.json") ) { uf::iostream << "Error loading `" << "./light/config.json" << "!" << "\n"; delete entity; return; } this->addChild(*entity); entity->initialize(); pod::Transform<>& parent = this->getComponent>(); pod::Transform<>& transform = entity->getComponent>(); entity->getComponent().getTransform().reference = &transform; transform = uf::transform::initialize( transform ); transform.position = parent.position; uf::transform::rotate( transform, transform.right, 1.5708 * 1 ); entity->getComponent().setFov(120); entity->getComponent().update(true); // ((ext::Light*)entity)->setColor( color ); uf::Serializer& lMetadata = entity->getComponent(); lMetadata["light"]["color"][0] = color.x; lMetadata["light"]["color"][1] = color.y; lMetadata["light"]["color"][2] = color.z; } /* Up */ if ( metadata["region"]["light"]["up"].asBool() ) { uf::Entity* entity = new ext::Light; if ( !((ext::Object*) entity)->load("./light/config.json") ) { uf::iostream << "Error loading `" << "./light/config.json" << "!" << "\n"; delete entity; return; } this->addChild(*entity); entity->initialize(); pod::Transform<>& parent = this->getComponent>(); pod::Transform<>& transform = entity->getComponent>(); entity->getComponent().getTransform().reference = &transform; transform = uf::transform::initialize( transform ); transform.position = parent.position; uf::transform::rotate( transform, transform.right, 1.5708 * 3 ); entity->getComponent().setFov(120); entity->getComponent().update(true); // ((ext::Light*)entity)->setColor( color ); uf::Serializer& lMetadata = entity->getComponent(); lMetadata["light"]["color"][0] = color.x; lMetadata["light"]["color"][1] = color.y; lMetadata["light"]["color"][2] = color.z; } } } } void ext::Region::render() { if ( !this->m_parent ) return; ext::World& root = this->getRootParent(); ext::Terrain& terrain = this->getParent(); uf::Entity::render(); if ( !this->hasComponent() ) return; if ( !this->getComponent().generated() ) return; if ( terrain.hasComponent() ) if ( terrain.getComponent().generated() ) return; pod::Transform<>& transform = this->getComponent>(); uf::Shader& shader = this->getParent().getComponent(); uf::Camera& camera = root.getCamera(); //root.getPlayer().getComponent(); uf::Mesh& mesh = this->getComponent(); uf::Serializer& metadata = this->getComponent(); const uf::Serializer& pMetadata = root.getComponent(); if ( !metadata["region"]["rasterized"].asBool() ) return; if ( metadata["region"]["unified"].asBool() ) return; // if ( pMetadata["terrain"]["unified"].asBool() ) return; int slot = 0; if ( this->getParent().hasComponent() ) { uf::Texture& texture = this->getParent().getComponent(); texture.bind(slot); } struct { int diffuse = 0; int specular = 1; int normal = 2; } slots; if ( this->getParent().hasComponent() ) { uf::Material& material = this->getParent().getComponent(); material.bind(slots.diffuse, slots.specular, slots.normal); } shader.bind(); { camera.update(); shader.push("model", uf::matrix::identity()); // shader.push("model", uf::transform::model(transform)); shader.push("view", camera.getView()); shader.push("projection", camera.getProjection()); if ( this->getParent().hasComponent() ) shader.push("texture", slot); if ( this->getParent().hasComponent() ) { if ( slots.diffuse >= 0 ) shader.push("diffuse", slots.diffuse); if ( slots.specular >= 0 ) shader.push("specular", slots.specular); if ( slots.normal >= 0 ) shader.push("normal", slots.normal); } } mesh.render(); }