diff --git a/src/game/ant/morphogenesis.cpp b/src/game/ant/morphogenesis.cpp index 02d4c78..1ef5663 100644 --- a/src/game/ant/morphogenesis.cpp +++ b/src/game/ant/morphogenesis.cpp @@ -60,7 +60,8 @@ static render::model* build_model const render::model* legs, const render::model* mandibles, const render::model* mesosoma, - const render::model* ocelli, + const render::model* lateral_ocelli, + const render::model* median_ocellus, const render::model* sting, const render::model* waist ); @@ -105,6 +106,8 @@ render::model* generate_worker(const ant::breed& breed) render::model* mesosoma_model = breed.mesosoma->model; render::model* sting_model = breed.sting->model; render::model* waist_model = breed.waist->model; + //render::model* lateral_ocelli_model = breed.ocelli->lateral_ocelli_model; + //render::model* median_ocellus_model = breed.ocelli->median_ocellus_model; // Build worker model render::model* model = build_model @@ -112,14 +115,15 @@ render::model* generate_worker(const ant::breed& breed) exoskeleton_material, antennae_model, eyes_model, - nullptr, + nullptr, // forewings gaster_model, head_model, - nullptr, + nullptr, // hindwings legs_model, mandibles_model, mesosoma_model, - nullptr, + nullptr, // lateral ocelli + nullptr, // median ocellus sting_model, waist_model ); @@ -182,7 +186,8 @@ render::model* build_model const render::model* legs, const render::model* mandibles, const render::model* mesosoma, - const render::model* ocelli, + const render::model* lateral_ocelli, + const render::model* median_ocellus, const render::model* sting, const render::model* waist ) @@ -199,7 +204,8 @@ render::model* build_model // Get vertex buffers of optional body parts const gl::vertex_buffer* sting_vbo = (sting) ? sting->get_vertex_buffer() : nullptr; const gl::vertex_buffer* eyes_vbo = (eyes) ? eyes->get_vertex_buffer() : nullptr; - const gl::vertex_buffer* ocelli_vbo = (ocelli) ? ocelli->get_vertex_buffer() : nullptr; + const gl::vertex_buffer* lateral_ocelli_vbo = (lateral_ocelli) ? lateral_ocelli->get_vertex_buffer() : nullptr; + const gl::vertex_buffer* median_ocellus_vbo = (median_ocellus) ? median_ocellus->get_vertex_buffer() : nullptr; const gl::vertex_buffer* forewings_vbo = (forewings) ? forewings->get_vertex_buffer() : nullptr; const gl::vertex_buffer* hindwings_vbo = (hindwings) ? hindwings->get_vertex_buffer() : nullptr; @@ -225,9 +231,12 @@ render::model* build_model std::size_t eyes_vbo_offset = vertex_buffer_size; if (eyes) vertex_buffer_size += eyes_vbo->get_size(); - std::size_t ocelli_vbo_offset = vertex_buffer_size; - if (ocelli) - vertex_buffer_size += ocelli_vbo->get_size(); + std::size_t lateral_ocelli_vbo_offset = vertex_buffer_size; + if (lateral_ocelli) + vertex_buffer_size += lateral_ocelli_vbo->get_size(); + std::size_t median_ocellus_vbo_offset = vertex_buffer_size; + if (median_ocellus) + vertex_buffer_size += median_ocellus_vbo->get_size(); std::size_t forewings_vbo_offset = vertex_buffer_size; if (forewings) vertex_buffer_size += forewings_vbo->get_size(); @@ -250,8 +259,10 @@ render::model* build_model sting_vbo->read(0, sting_vbo->get_size(), vertex_buffer_data + sting_vbo_offset); if (eyes) eyes_vbo->read(0, eyes_vbo->get_size(), vertex_buffer_data + eyes_vbo_offset); - if (ocelli) - ocelli_vbo->read(0, ocelli_vbo->get_size(), vertex_buffer_data + ocelli_vbo_offset); + if (lateral_ocelli) + lateral_ocelli_vbo->read(0, lateral_ocelli_vbo->get_size(), vertex_buffer_data + lateral_ocelli_vbo_offset); + if (median_ocellus) + median_ocellus_vbo->read(0, median_ocellus_vbo->get_size(), vertex_buffer_data + median_ocellus_vbo_offset); if (forewings) forewings_vbo->read(0, forewings_vbo->get_size(), vertex_buffer_data + forewings_vbo_offset); if (hindwings) @@ -293,7 +304,8 @@ render::model* build_model const render::skeleton& gaster_skeleton = gaster->get_skeleton(); const render::skeleton* sting_skeleton = (sting) ? &sting->get_skeleton() : nullptr; const render::skeleton* eyes_skeleton = (eyes) ? &eyes->get_skeleton() : nullptr; - const render::skeleton* ocelli_skeleton = (ocelli) ? &ocelli->get_skeleton() : nullptr; + const render::skeleton* lateral_ocelli_skeleton = (lateral_ocelli) ? &lateral_ocelli->get_skeleton() : nullptr; + const render::skeleton* median_ocellus_skeleton = (median_ocellus) ? &median_ocellus->get_skeleton() : nullptr; bool postpetiole = (waist_skeleton.bone_map.find("postpetiole") != waist_skeleton.bone_map.end()); // Allocate skeleton bones @@ -530,7 +542,8 @@ render::model* build_model std::size_t gaster_index_count = (*gaster->get_groups())[0]->get_index_count(); std::size_t sting_index_count = (sting) ? (*sting->get_groups())[0]->get_index_count() : 0; std::size_t eyes_index_count = (eyes) ? (*eyes->get_groups())[0]->get_index_count() : 0; - std::size_t ocelli_index_count = (ocelli) ? (*ocelli->get_groups())[0]->get_index_count() : 0; + std::size_t lateral_ocelli_index_count = (lateral_ocelli) ? (*lateral_ocelli->get_groups())[0]->get_index_count() : 0; + std::size_t median_ocellus_index_count = (median_ocellus) ? (*median_ocellus->get_groups())[0]->get_index_count() : 0; std::size_t forewings_index_count = (forewings) ? (*forewings->get_groups())[0]->get_index_count() : 0; std::size_t hindwings_index_count = (hindwings) ? (*hindwings->get_groups())[0]->get_index_count() : 0; std::size_t exoskeleton_index_count = @@ -668,7 +681,7 @@ render::model* build_model if (auto it = head_skeleton.bone_map.find("eye_l"); it != head_skeleton.bone_map.end()) eye_l_to_body = head_to_body * head_skeleton.concatenate(it->second); math::transform eye_r_to_body; - if (auto it =head_skeleton.bone_map.find("eye_r"); it != head_skeleton.bone_map.end()) + if (auto it = head_skeleton.bone_map.find("eye_r"); it != head_skeleton.bone_map.end()) eye_r_to_body = head_to_body * head_skeleton.concatenate(it->second); // Reskin eye bones @@ -682,11 +695,44 @@ render::model* build_model reskin_vertices(vertex_buffer_data + eyes_vbo_offset, eyes_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_eye_r_bone_indices, head_bone_index, eye_r_to_body); } + if (lateral_ocelli) + { + // Calculate transforms from lateral ocelli space to body space + math::transform ocellus_l_to_body; + if (auto it = head_skeleton.bone_map.find("ocellus_l"); it != head_skeleton.bone_map.end()) + ocellus_l_to_body = head_to_body * head_skeleton.concatenate(it->second); + math::transform ocellus_r_to_body; + if (auto it = head_skeleton.bone_map.find("ocellus_r"); it != head_skeleton.bone_map.end()) + ocellus_r_to_body = head_to_body * head_skeleton.concatenate(it->second); + + // Reskin lateral ocelli bones + std::unordered_set old_ocellus_l_bone_indices; + if (auto it = lateral_ocelli_skeleton->bone_map.find("ocellus_l"); it != lateral_ocelli_skeleton->bone_map.end()) + old_ocellus_l_bone_indices.emplace(it->second); + reskin_vertices(vertex_buffer_data + lateral_ocelli_vbo_offset, lateral_ocelli_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_ocellus_l_bone_indices, head_bone_index, ocellus_l_to_body); + std::unordered_set old_ocellus_r_bone_indices; + if (auto it = lateral_ocelli_skeleton->bone_map.find("ocellus_r"); it != lateral_ocelli_skeleton->bone_map.end()) + old_ocellus_r_bone_indices.emplace(it->second); + reskin_vertices(vertex_buffer_data + lateral_ocelli_vbo_offset, lateral_ocelli_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_ocellus_r_bone_indices, head_bone_index, ocellus_r_to_body); + } + + if (median_ocellus) + { + // Calculate transforms from lateral ocelli space to body space + math::transform ocellus_m_to_body; + if (auto it = head_skeleton.bone_map.find("ocellus_m"); it != head_skeleton.bone_map.end()) + ocellus_m_to_body = head_to_body * head_skeleton.concatenate(it->second); + + // Reskin lateral ocelli bones + std::unordered_set old_ocellus_m_bone_indices; + if (auto it = median_ocellus_skeleton->bone_map.find("ocellus_m"); it != median_ocellus_skeleton->bone_map.end()) + old_ocellus_m_bone_indices.emplace(it->second); + reskin_vertices(vertex_buffer_data + median_ocellus_vbo_offset, median_ocellus_index_count, *position_attribute, *normal_attribute, *tangent_attribute, *bone_index_attribute, old_ocellus_m_bone_indices, head_bone_index, ocellus_m_to_body); + } + // Upload vertex buffer data to model VBO model->get_vertex_buffer()->repurpose(gl::buffer_usage::static_draw, vertex_buffer_size, vertex_buffer_data); - - // Construct exoskeleton model group render::model_group* exoskeleton_group = model->add_group("exoskeleton"); exoskeleton_group->set_material(exoskeleton_material); @@ -706,15 +752,29 @@ render::model* build_model index_offset += eyes_index_count; } - if (ocelli) + if (lateral_ocelli || median_ocellus) { // Construct ocelli model group render::model_group* ocelli_group = model->add_group("ocelli"); - ocelli_group->set_material((*ocelli->get_groups())[0]->get_material()); ocelli_group->set_drawing_mode(gl::drawing_mode::triangles); ocelli_group->set_start_index(index_offset); - ocelli_group->set_index_count(ocelli_index_count); - index_offset += ocelli_index_count; + + std::size_t index_count = 0; + if (lateral_ocelli) + { + index_count += lateral_ocelli_index_count; + index_offset += lateral_ocelli_index_count; + ocelli_group->set_material((*lateral_ocelli->get_groups())[0]->get_material()); + } + if (median_ocellus) + { + index_count += median_ocellus_index_count; + index_offset += median_ocellus_index_count; + if (!lateral_ocelli) + ocelli_group->set_material((*median_ocellus->get_groups())[0]->get_material()); + } + + ocelli_group->set_index_count(index_count); } if (forewings) diff --git a/src/game/ant/trait/loader/ocelli-loader.cpp b/src/game/ant/trait/loader/ocelli-loader.cpp index 2ba46ba..fccef69 100644 --- a/src/game/ant/trait/loader/ocelli-loader.cpp +++ b/src/game/ant/trait/loader/ocelli-loader.cpp @@ -40,29 +40,16 @@ trait::ocelli* resource_loader::load(resource_manager* resource_m // Allocate ocelli trait trait::ocelli* ocelli = new trait::ocelli(); - // Load ocelli model (if not null) - auto model_element = ocelli_element->find("model"); - if (model_element == ocelli_element->end()) - throw std::runtime_error("Ocelli trait doesn't specify ocelli model."); - if (model_element->is_null()) - { - ocelli->model = nullptr; - } - else - { - ocelli->model = resource_manager->load(model_element->get()); - } + // Parse lateral ocelli + ocelli->lateral_ocelli = false; + if (auto lateral_ocelli_element = ocelli_element->find("lateral_ocelli"); lateral_ocelli_element != ocelli_element->end()) + ocelli->lateral_ocelli = lateral_ocelli_element->get(); // Parse median ocellus ocelli->median_ocellus = false; if (auto median_ocellus_element = ocelli_element->find("median_ocellus"); median_ocellus_element != ocelli_element->end()) ocelli->median_ocellus = median_ocellus_element->get(); - // Parse lateral ocelli - ocelli->lateral_ocelli = false; - if (auto lateral_ocelli_element = ocelli_element->find("lateral_ocelli"); lateral_ocelli_element != ocelli_element->end()) - ocelli->lateral_ocelli = lateral_ocelli_element->get(); - // Parse ocelli width ocelli->width = 0.0f; if (auto width_element = ocelli_element->find("width"); width_element != ocelli_element->end()) @@ -73,6 +60,34 @@ trait::ocelli* resource_loader::load(resource_manager* resource_m if (auto height_element = ocelli_element->find("height"); height_element != ocelli_element->end()) ocelli->height = height_element->get(); + // Load lateral ocelli model (if not null) + if (ocelli->lateral_ocelli) + { + auto lateral_ocelli_model_element = ocelli_element->find("lateral_ocelli_model"); + if (lateral_ocelli_model_element == ocelli_element->end() || lateral_ocelli_model_element->is_null()) + throw std::runtime_error("Ocelli trait doesn't specify lateral ocelli model."); + + ocelli->lateral_ocelli_model = resource_manager->load(lateral_ocelli_model_element->get()); + } + else + { + ocelli->lateral_ocelli_model = nullptr; + } + + // Load median ocellus model (if not null) + if (ocelli->median_ocellus) + { + auto median_ocellus_model_element = ocelli_element->find("median_ocellus_model"); + if (median_ocellus_model_element == ocelli_element->end() || median_ocellus_model_element->is_null()) + throw std::runtime_error("Ocelli trait doesn't specify median ocellus model."); + + ocelli->median_ocellus_model = resource_manager->load(median_ocellus_model_element->get()); + } + else + { + ocelli->median_ocellus_model = nullptr; + } + // Free JSON data delete data; diff --git a/src/game/ant/trait/ocelli.hpp b/src/game/ant/trait/ocelli.hpp index 03fb800..27e3f3b 100644 --- a/src/game/ant/trait/ocelli.hpp +++ b/src/game/ant/trait/ocelli.hpp @@ -31,20 +31,23 @@ namespace trait { */ struct ocelli { - /// Median ocellus present. - bool median_ocellus; - /// Lateral ocelli present. bool lateral_ocelli; + /// Median ocellus present. + bool median_ocellus; + /// Ocellus width, in mesosomal lengths. float width; /// Ocellus height, in mesosomal lengths. float height; - /// 3D model of the ocelli. - render::model* model; + /// 3D model of the lateral ocelli. + render::model* lateral_ocelli_model; + + /// 3D model of the median ocellus. + render::model* median_ocellus_model; }; } // namespace trait diff --git a/src/game/state/nuptial-flight.cpp b/src/game/state/nuptial-flight.cpp index d2db7f0..5c35852 100644 --- a/src/game/state/nuptial-flight.cpp +++ b/src/game/state/nuptial-flight.cpp @@ -66,7 +66,7 @@ nuptial_flight::nuptial_flight(game::context& ctx): breed.legs = ctx.resource_manager->load("trekking-legs.dna"); breed.waist = ctx.resource_manager->load("harvester-waist.dna"); breed.gaster = ctx.resource_manager->load("ovoid-gaster.dna"); - breed.ocelli = ctx.resource_manager->load("absent-ocelli.dna"); + breed.ocelli = ctx.resource_manager->load("trinocular-fisheye-ocelli.dna"); breed.sting = ctx.resource_manager->load("sting-absent.dna"); breed.sculpturing = ctx.resource_manager->load("politus-sculpturing.dna"); breed.pigmentation = ctx.resource_manager->load("rust-pigmentation.dna");