diff --git a/src/CRE/mdl/disp_manager.cpp b/src/CRE/mdl/disp_manager.cpp index e9353c12..c1b383d7 100644 --- a/src/CRE/mdl/disp_manager.cpp +++ b/src/CRE/mdl/disp_manager.cpp @@ -75,6 +75,23 @@ texture_data_struct::texture_data_struct() : field_0() { } namespace mdl { + static void gen_capsule_indices(std::vector& indices, + int32_t slices, int32_t stacks, float_t length, bool wire, size_t start); + static void gen_capsule_vertices(etc_obj_vertex_data* data, + int32_t slices, int32_t stacks, float_t length, float_t radius); + + static void gen_cylinder_indices(std::vector& indices, + int32_t slices, int32_t stacks, bool wire, size_t start); + static void gen_cylinder_vertices(etc_obj_vertex_data* data, + int32_t slices, int32_t stacks, float_t base, float_t height); + + static void gen_sphere_indices(std::vector& indices, + int32_t slices, int32_t stacks, bool wire, size_t start); + static void gen_sphere_vertices(etc_obj_vertex_data* data, + int32_t slices, int32_t stacks, float_t radius); + + static void set_default_vertex_attrib(); + ObjSubMeshArgs::ObjSubMeshArgs() : sub_mesh(), mesh(), material(), textures(), mat_count(), mats(), vertex_buffer(), vertex_buffer_offset(), index_buffer(), set_blend_color(), chara_color(), self_shadow(), shadow(), morph_vertex_buffer(), morph_vertex_buffer_offset(), morph_weight(), texture_pattern_count(), @@ -143,7 +160,47 @@ namespace mdl { } - EtcObj::EtcObj(EtcObjType type) : count(), offset() { + EtcObj::Data::Data(const EtcObjTeapot& other) : capsule() { + teapot = other; + } + + EtcObj::Data::Data(const EtcObjGrid& other) : capsule() { + grid = other; + } + + EtcObj::Data::Data(const EtcObjCube& other) : capsule() { + cube = other; + } + + EtcObj::Data::Data(const EtcObjSphere& other) : capsule() { + sphere = other; + } + + EtcObj::Data::Data(const EtcObjPlane& other) : capsule() { + plane = other; + } + + EtcObj::Data::Data(const EtcObjCone& other) : capsule() { + cone = other; + } + + EtcObj::Data::Data(const EtcObjLine& other) : capsule() { + line = other; + } + + EtcObj::Data::Data(const EtcObjCross& other) : capsule() { + cross = other; + } + + EtcObj::Data::Data(const EtcObjCapsule& other) : capsule() { + capsule = other; + } + + EtcObj::Data::Data(const EtcObjCylinder& other) : capsule() { + cylinder = other; + } + + EtcObj::EtcObj(EtcObjType type) { this->type = type; color = 0xFFFFFFFF; constant = false; @@ -209,12 +266,31 @@ namespace mdl { } - void ObjData::init_etc(DispManager* disp_manager, const mat4& mat, const mdl::EtcObj& etc) { + void ObjData::init_etc(DispManager* disp_manager, + const mat4& mat, int32_t index, int32_t count, const EtcObj& etc) { kind = mdl::OBJ_KIND_ETC; this->mat = mat; - args.etc = etc; + args.etc.color = etc.color; + args.etc.constant = etc.constant; + args.etc.index = index; + args.etc.count = count; - disp_manager->add_vertex_array(&args.etc, this->mat); + if (etc.type == mdl::ETC_OBJ_CAPSULE) { + const EtcObjCapsule& capsule = etc.data.capsule; + + vec3 origin = (capsule.pos[0] + capsule.pos[1]) * 0.5f; + mat4_add_translate(&this->mat, &origin, &this->mat); + + const vec3 dir = vec3::normalize(capsule.pos[1] - capsule.pos[0]); + const vec3 up = { 0.0f, 0.0f, 1.0f }; + vec3 axis; + float_t angle; + vec3::axis_angle_from_vectors(axis, angle, up, dir); + + mat4 m = mat4_identity; + mat4_mul_rotation(&m, &axis, angle, &m); + mat4_mul(&m, &this->mat, &this->mat); + } } void ObjData::init_sub_mesh(DispManager* disp_manager, const mat4& mat, float_t radius, const obj_sub_mesh* sub_mesh, @@ -294,6 +370,695 @@ namespace mdl { args.user.data = data; } + EtcObjManager::EtcObjManager() : vao(), vbo_vertex_count(), ebo_index_count() { + vbo_vertex_count = 256; + ebo_index_count = 256; + + static const GLsizei buffer_size = sizeof(etc_obj_vertex_data); + + vbo.Create(gl_state, buffer_size * vbo_vertex_count); + ebo.Create(gl_state, sizeof(uint32_t) * ebo_index_count); + + glGenVertexArrays(1, &vao); + gl_state.bind_vertex_array(vao); + gl_state.bind_array_buffer(vbo, true); + gl_state.bind_element_array_buffer(ebo, true); + + set_default_vertex_attrib(); + + glEnableVertexAttribArray(POSITION_INDEX); + glVertexAttribPointer(POSITION_INDEX, 3, GL_FLOAT, GL_FALSE, buffer_size, + (void*)offsetof(etc_obj_vertex_data, position)); + glEnableVertexAttribArray(NORMAL_INDEX); + glVertexAttribPointer(NORMAL_INDEX, 3, GL_FLOAT, GL_FALSE, buffer_size, + (void*)offsetof(etc_obj_vertex_data, normal)); + + gl_state.bind_array_buffer(0); + gl_state.bind_vertex_array(0); + gl_state.bind_element_array_buffer(0); + + } + + EtcObjManager::~EtcObjManager() { + if (vao) { + glDeleteVertexArrays(1, &vao); + vao = 0; + } + + ebo.Destroy(); + vbo.Destroy(); + } + + bool EtcObjManager::add_capsule(int32_t& index, int32_t& count, const EtcObjCapsule& capsule) { + if (capsule.slices < 2 || capsule.stacks < 2) + return false; + + const float_t length = vec3::distance(capsule.pos[0], capsule.pos[1]); + if (length < 0.00000f) { + EtcObjSphere sphere = {}; + sphere.radius = capsule.radius; + sphere.slices = capsule.slices; + sphere.stacks = capsule.stacks; + sphere.wire = capsule.wire; + return add_sphere(index, count, sphere); + } + + for (const auto& i : etc_obj_buffer) { + if (i.first.first != ETC_OBJ_CAPSULE) + continue; + + const EtcObjCapsule& other_capsule = i.second.capsule; + if (other_capsule.slices == capsule.slices + && ((other_capsule.stacks + 1)) >> 1 == ((capsule.stacks + 1) >> 1) + && fabsf(other_capsule.radius - capsule.radius) < 0.00001f + && fabsf(vec3::distance(other_capsule.pos[0], other_capsule.pos[1]) - length) < 0.00001f) { + index = i.first.second; + count = 1; + return true; + } + } + + index = (int32_t)draw_param_buffer.size(); + count = 1; + + etc_obj_vertex_data* vtx_data = 0; + const size_t stacks = (((size_t)capsule.stacks + 1) / 2) * 2; + size_t vtx_count = (size_t)capsule.slices * stacks + 2; + size_t start = add_data(vtx_data, vtx_count); + + gen_capsule_vertices(vtx_data, capsule.slices, capsule.stacks, length, capsule.radius); + + draw_param_buffer.push_back({}); + etc_obj_draw_param& draw_param = draw_param_buffer.back(); + + draw_param.attrib.m.primitive = capsule.wire ? GL_LINES : GL_TRIANGLES; + draw_param.start = (GLuint)start; + + size_t idx_offset = index_buffer.size(); + gen_capsule_indices(index_buffer, capsule.slices, capsule.stacks, length, capsule.wire, start); + + draw_param.end = (GLuint)(start + vtx_count - 1); + draw_param.offset = (GLintptr)(idx_offset * sizeof(uint32_t)); + draw_param.count = (GLsizei)(index_buffer.size() - idx_offset); + + etc_obj_buffer.push_back({ ETC_OBJ_CAPSULE, index }, capsule); + return true; + } + + bool EtcObjManager::add_cone(int32_t& index, int32_t& count, const EtcObjCone& cone) { + for (const auto& i : etc_obj_buffer) { + if (i.first.first != ETC_OBJ_CONE) + continue; + + const EtcObjCone& other_cone = i.second.cone; + if (other_cone.slices == cone.slices + && other_cone.stacks == cone.stacks + && fabsf(other_cone.base - cone.base) < 0.00001f + && fabsf(other_cone.height - cone.height) < 0.00001f + && other_cone.wire == cone.wire) { + index = i.first.second; + count = cone.wire ? 2 : 1; + return true; + } + } + + const float_t base = cone.base; + const float_t height = cone.height; + const int32_t slices = cone.slices; + const int32_t stacks = cone.stacks; + + const float_t slice_step = (float_t)((M_PI * 2.0) / (double_t)slices); + + if (!cone.wire) { + etc_obj_vertex_data* vtx_data = 0; + int32_t _index = 0; + if (add_data(_index, vtx_data, (size_t)slices * 3, GL_TRIANGLES)) { + index = _index; + count = 1; + + float_t slice_angle = (float_t)-1 * slice_step; + float_t x = cosf(slice_angle); + float_t y = sinf(slice_angle); + + const float_t cosn = base / sqrtf(height * height + base * base); + const float_t sinn = 1.0f - cosn * cosn; + + etc_obj_vertex_data vtx2 = { vec3(x * base, y * base, 0.0f), vec3(x * sinn, y * sinn, cosn) }; + for (int32_t j = 0; j < slices; j++) { + float_t slice_angle0 = ((float_t)j - 0.5f) * slice_step; + float_t x0 = cosf(slice_angle0); + float_t y0 = sinf(slice_angle0); + + vtx_data[0] = { vec3(0.0f, 0.0f, height), vec3(x0 * sinn, y0 * sinn, cosn) }; + vtx_data[1] = vtx2; + + float_t slice_angle2 = (float_t)j * slice_step; + float_t x2 = cosf(slice_angle2); + float_t y2 = sinf(slice_angle2); + + vtx2 = { vec3(x2 * base, y2 * base, 0.0f), vec3(x2 * sinn, y2 * sinn, cosn) }; + vtx_data[2] = vtx2; + + vtx_data += 3; + } + + etc_obj_buffer.push_back({ ETC_OBJ_CONE, index }, cone); + return true; + } + } + else { + const float_t cosn = base / sqrtf(height * height + base * base); + const float_t sinn = 1.0f - cosn * cosn; + + etc_obj_vertex_data* vtx_data = 0; + int32_t _index = 0; + if (add_data(_index, vtx_data, ((size_t)slices + 1) * stacks + 1, GL_LINE_STRIP)) { + index = _index; + count = 2; + + for (int32_t i = 0; i < stacks; i++) { + const float_t xy = (1.0f - (float_t)i * (1.0f / stacks)) * base; + const float_t z = (float_t)i * height * (1.0f / stacks); + for (int32_t j = 0; j <= slices; j++) { + float_t slice_angle = (float_t)j * slice_step; + float_t x = cosf(slice_angle); + float_t y = sinf(slice_angle); + *vtx_data++ = { vec3(x * xy, y * xy, z), vec3(x * sinn, y * sinn, cosn) }; + } + } + *vtx_data++ = { vec3(0.0f, 0.0f, height), vec3(0.0f, 0.0f, 1.0f) }; + + int32_t _index = 0; + if (add_data(_index, vtx_data, ((size_t)slices - 1) * 2, GL_LINES)) { + for (int32_t j = 1; j < slices; j++) { + float_t slice_angle = (float_t)j * slice_step; + float_t x = cosf(slice_angle); + float_t y = sinf(slice_angle); + vtx_data[0] = { vec3(x * base, y * base, 0.0f), vec3(x * sinn, y * sinn, cosn) }; + vtx_data[1] = { vec3(0.0f, 0.0f, height), vec3(x * sinn, y * sinn, cosn) }; + vtx_data += 2; + } + + etc_obj_buffer.push_back({ ETC_OBJ_CONE, index }, cone); + return true; + } + } + } + return false; + } + + bool EtcObjManager::add_cross(int32_t& index, int32_t& count, const EtcObjCross& cross) { + if (fabsf(cross.size) < 0.00001f) + return false; + + for (const auto& i : etc_obj_buffer) { + if (i.first.first != ETC_OBJ_CROSS) + continue; + + const EtcObjCross& other_cross = i.second.cross; + if (fabsf(other_cross.size - cross.size) < 0.00001f) { + index = i.first.second; + count = 1; + return true; + } + } + + int32_t _index = 0; + etc_obj_vertex_data* vtx_data = 0; + if (add_data(_index, vtx_data, 6, GL_LINES)) { + index = _index; + count = 1; + + const float_t size = cross.size; + + vtx_data[0] = vec3(-size, 0.0f, 0.0f); + vtx_data[1] = vec3( size, 0.0f, 0.0f); + vtx_data[2] = vec3( 0.0f, -size, 0.0f); + vtx_data[3] = vec3( 0.0f, size, 0.0f); + vtx_data[4] = vec3( 0.0f, 0.0f, -size); + vtx_data[5] = vec3( 0.0f, 0.0f, size); + + etc_obj_buffer.push_back({ ETC_OBJ_CROSS, index }, cross); + return true; + } + return false; + } + + bool EtcObjManager::add_cube(int32_t& index, int32_t& count, const EtcObjCube& cube) { + if (fabsf(cube.size.x) < 0.00001f || fabsf(cube.size.y) < 0.00001f || fabsf(cube.size.z) < 0.00001f) + return false; + + for (const auto& i : etc_obj_buffer) { + if (i.first.first != ETC_OBJ_CUBE) + continue; + + const EtcObjCube& other_cube = i.second.cube; + if (vec3::dot(vec3::abs(other_cube.size - cube.size), 1.0f) < 0.00001f) { + index = i.first.second; + count = cube.wire ? 2 : 1; + return true; + } + } + + const vec3 size = cube.size * 0.5f; + + const vec3 vtx_array[] = { + { -size.x, -size.y, -size.z }, + { -size.x, -size.y, size.z }, + { size.x, -size.y, size.z }, + { size.x, -size.y, -size.z }, + { -size.x, size.y, -size.z }, + { -size.x, size.y, size.z }, + { size.x, size.y, size.z }, + { size.x, size.y, -size.z }, + }; + + int32_t _index = 0; + etc_obj_vertex_data* vtx_data = 0; + if (!cube.wire) { + if (add_data(_index, vtx_data, 36, GL_TRIANGLES)) { + index = _index; + count = 1; + + struct cube_face_data { + int32_t vtx_idx[4]; + vec3 normal; + }; + + const cube_face_data face_array[] = { + { { 5, 1, 2, 6 }, vec3( 0.0f, 0.0f, 1.0f) }, + { { 6, 2, 3, 7 }, vec3( 1.0f, 0.0f, 0.0f) }, + { { 7, 3, 0, 4 }, vec3( 0.0f, 0.0f, -1.0f) }, + { { 4, 0, 1, 5 }, vec3(-1.0f, 0.0f, 0.0f) }, + { { 4, 5, 6, 7 }, vec3( 0.0f, 1.0f, 0.0f) }, + { { 1, 0, 3, 2 }, vec3( 0.0f, -1.0f, 0.0f) }, + }; + + const cube_face_data* face = face_array; + + for (int32_t i = 0; i < 6; i++) { + vtx_data[0].position = vtx_array[face[i].vtx_idx[0]]; + vtx_data[0].normal = face[i].normal; + vtx_data[1].position = vtx_array[face[i].vtx_idx[1]]; + vtx_data[1].normal = face[i].normal; + vtx_data[2].position = vtx_array[face[i].vtx_idx[3]]; + vtx_data[2].normal = face[i].normal; + vtx_data[3].position = vtx_array[face[i].vtx_idx[3]]; + vtx_data[3].normal = face[i].normal; + vtx_data[4].position = vtx_array[face[i].vtx_idx[1]]; + vtx_data[4].normal = face[i].normal; + vtx_data[5].position = vtx_array[face[i].vtx_idx[2]]; + vtx_data[5].normal = face[i].normal; + vtx_data += 6; + } + + etc_obj_buffer.push_back({ ETC_OBJ_CUBE, index }, cube); + return true; + } + } + else { + if (add_data(_index, vtx_data, 10, GL_LINE_STRIP)) { + index = _index; + count = 2; + + vtx_data[0] = vtx_array[0]; + vtx_data[1] = vtx_array[1]; + vtx_data[2] = vtx_array[5]; + vtx_data[3] = vtx_array[4]; + vtx_data[4] = vtx_array[0]; + vtx_data[5] = vtx_array[3]; + vtx_data[6] = vtx_array[2]; + vtx_data[7] = vtx_array[6]; + vtx_data[8] = vtx_array[7]; + vtx_data[9] = vtx_array[3]; + vtx_data += 10; + + if (add_data(_index, vtx_data, 6, GL_LINES)) { + vtx_data[0] = vtx_array[4]; + vtx_data[1] = vtx_array[7]; + vtx_data[2] = vtx_array[5]; + vtx_data[3] = vtx_array[6]; + vtx_data[4] = vtx_array[1]; + vtx_data[5] = vtx_array[2]; + vtx_data += 6; + + etc_obj_buffer.push_back({ ETC_OBJ_CUBE, index }, cube); + return true; + } + } + } + return false; + } + + bool EtcObjManager::add_cylinder(int32_t& index, int32_t& count, const EtcObjCylinder& cylinder) { + if (cylinder.slices < 2 || cylinder.stacks < 0) + return false; + + for (const auto& i : etc_obj_buffer) { + if (i.first.first != ETC_OBJ_CYLINDER) + continue; + + const EtcObjCylinder& other_cylinder = i.second.cylinder; + if (other_cylinder.slices == cylinder.slices + && other_cylinder.stacks == cylinder.stacks + && fabsf(other_cylinder.base - cylinder.base) < 0.00001f + && fabsf(other_cylinder.height - cylinder.height) < 0.00001f) { + index = i.first.second; + count = 1; + return true; + } + } + + index = (int32_t)draw_param_buffer.size(); + count = 1; + + etc_obj_vertex_data* vtx_data = 0; + size_t vtx_count = ((size_t)cylinder.slices * ((size_t)cylinder.stacks + 1) + 2); + size_t start = add_data(vtx_data, vtx_count); + + gen_cylinder_vertices(vtx_data, cylinder.slices, cylinder.stacks, cylinder.base, cylinder.height); + + draw_param_buffer.push_back({}); + etc_obj_draw_param& draw_param = draw_param_buffer.back(); + + draw_param.attrib.m.primitive = cylinder.wire ? GL_LINES : GL_TRIANGLES; + draw_param.start = (GLuint)start; + + size_t idx_offset = index_buffer.size(); + gen_cylinder_indices(index_buffer, cylinder.slices, cylinder.stacks, cylinder.wire, start); + + draw_param.end = (GLuint)(start + vtx_count - 1); + draw_param.offset = (GLintptr)(idx_offset * sizeof(uint32_t)); + draw_param.count = (GLsizei)(index_buffer.size() - idx_offset); + + etc_obj_buffer.push_back({ ETC_OBJ_CYLINDER, index }, cylinder); + return true; + } + + + template + size_t EtcObjManager::add_data(T*& data, size_t num_vertex) { + size_t size = vertex_buffer.size(); + size_t align_offset = (sizeof(T) - size % sizeof(T)) % sizeof(T); + size_t vertex_array_size = sizeof(T) * num_vertex; + + vertex_buffer.resize(size + align_offset + vertex_array_size); + T* vtx_data = (T*)(vertex_buffer.data() + size + align_offset); + data = vtx_data; + return (uint32_t)((size + align_offset) / sizeof(T)); + } + + template + bool EtcObjManager::add_data(int32_t& index, T*& data, size_t num_vertex, GLenum primitive) { + size_t size = vertex_buffer.size(); + size_t align_offset = (sizeof(T) - size % sizeof(T)) % sizeof(T); + size_t vertex_array_size = sizeof(T) * num_vertex; + + draw_param_buffer.push_back({}); + etc_obj_draw_param& draw_param = draw_param_buffer.back(); + draw_param.attrib.m.primitive = primitive; + draw_param.first = (GLint)(uint32_t)((size + align_offset) / sizeof(T)); + draw_param.count = (GLsizei)num_vertex; + + index = (int32_t)(draw_param_buffer.size() - 1); + + if (vertex_buffer.size() < size + align_offset + vertex_array_size) + vertex_buffer.resize(size + align_offset + vertex_array_size); + + T* vtx_data = (T*)(vertex_buffer.data() + size + align_offset); + data = vtx_data; + return true; + } + + bool EtcObjManager::add_grid(int32_t& index, int32_t& count, const EtcObjGrid& grid) { + if (grid.ws < 1 || grid.hs < 1) + return false; + + for (const auto& i : etc_obj_buffer) { + if (i.first.first != ETC_OBJ_GRID) + continue; + + const EtcObjGrid& other_grid = i.second.grid; + if (!memcmp(&other_grid, &grid, sizeof(EtcObjGrid))) { + index = i.first.second; + count = 1; + return true; + } + } + + int32_t _index = 0; + etc_obj_vertex_data* vtx_data = 0; + if (add_data(_index, vtx_data, ((size_t)grid.ws + grid.hs) * 2, GL_LINES)) { + index = _index; + count = 2; + + const int32_t ws = grid.ws; + const int32_t hs = grid.hs; + const int32_t ws_half = grid.ws / 2; + const int32_t hs_half = grid.hs / 2; + + const float_t width = (float_t)grid.w * 0.5f; + const float_t height = (float_t)grid.h * 0.5f; + const float_t ws_half_flt = (float_t)ws_half; + const float_t hs_half_flt = (float_t)hs_half; + + for (int32_t i = 0; i <= ws; i++) { + if (ws_half == i) + continue; + + const float_t w = ((float_t)i * (width / ws_half_flt)) - width; + vtx_data[0] = vec3(w, 0.0f, -height); + vtx_data[1] = vec3(w, 0.0f, height); + vtx_data += 2; + } + + for (int32_t i = 0; i <= hs; i++) { + if (hs_half == i) + continue; + + const float_t h = ((float_t)i * (height / hs_half_flt)) - height; + vtx_data[0] = vec3(-width, 0.0f, h); + vtx_data[1] = vec3( width, 0.0f, h); + vtx_data += 2; + } + + if (add_data(_index, vtx_data, 4, GL_LINES)) { + vtx_data[0] = vec3( 0.0f, 0.0f, -height); + vtx_data[1] = vec3( 0.0f, 0.0f, height); + vtx_data[2] = vec3(-width, 0.0f, 0.0f); + vtx_data[3] = vec3( width, 0.0f, 0.0f); + vtx_data += 4; + + etc_obj_buffer.push_back({ ETC_OBJ_GRID, index }, grid); + return true; + } + } + return false; + } + + bool EtcObjManager::add_line(int32_t& index, int32_t& count, const EtcObjLine& line) { + if (vec3::distance(line.pos[0], line.pos[1]) < 0.00001f) + return false; + + for (const auto& i : etc_obj_buffer) { + if (i.first.first != ETC_OBJ_LINE) + continue; + + const EtcObjLine& other_line = i.second.line; + if (other_line.pos[0] == line.pos[0] + && other_line.pos[1] == line.pos[1]) { + index = i.first.second; + count = 1; + return true; + } + } + + int32_t _index = 0; + etc_obj_vertex_data* vtx_data = 0; + if (add_data(_index, vtx_data, 2, GL_LINES)) { + index = _index; + count = 1; + + vtx_data[0] = line.pos[0]; + vtx_data[1] = line.pos[1]; + vtx_data += 2; + + etc_obj_buffer.push_back({ ETC_OBJ_LINE, index }, line); + return true; + } + return false; + } + + bool EtcObjManager::add_obj(int32_t& index, int32_t& count, const EtcObj& etc) { + switch (etc.type) { + case mdl::ETC_OBJ_GRID: + return add_grid(index, count, etc.data.grid); + case mdl::ETC_OBJ_CUBE: + return add_cube(index, count, etc.data.cube); + case mdl::ETC_OBJ_SPHERE: + return add_sphere(index, count, etc.data.sphere); + case mdl::ETC_OBJ_PLANE: + return add_plane(index, count, etc.data.plane); + case mdl::ETC_OBJ_CONE: + return add_cone(index, count, etc.data.cone); + case mdl::ETC_OBJ_LINE: + return add_line(index, count, etc.data.line); + case mdl::ETC_OBJ_CROSS: + return add_cross(index, count, etc.data.cross); + case mdl::ETC_OBJ_CAPSULE: // Added + return add_capsule(index, count, etc.data.capsule); + case mdl::ETC_OBJ_CYLINDER: // Added + return add_cylinder(index, count, etc.data.cylinder); + default: + return false; + } + } + + bool EtcObjManager::add_plane(int32_t& index, int32_t& count, const EtcObjPlane& plane) { + if (!plane.w || !plane.h) + return false; + + for (const auto& i : etc_obj_buffer) { + if (i.first.first != ETC_OBJ_PLANE) + continue; + + const EtcObjPlane& other_plane = i.second.plane; + if (other_plane.w == plane.w && other_plane.h == plane.h) { + index = i.first.second; + count = 1; + return true; + } + } + + int32_t _index = 0; + etc_obj_vertex_data* vtx_data = 0; + if (add_data(_index, vtx_data, 4, GL_TRIANGLE_STRIP)) { + index = _index; + count = 1; + + const float_t width = (float_t)plane.w * 0.5f; + const float_t height = (float_t)plane.h * 0.5f; + + vtx_data[0] = vec3( width, 0.0f, height); + vtx_data[1] = vec3( width, 0.0f, -height); + vtx_data[2] = vec3(-width, 0.0f, height); + vtx_data[3] = vec3(-width, 0.0f, -height); + vtx_data += 4; + + etc_obj_buffer.push_back({ ETC_OBJ_PLANE, index }, plane); + return true; + } + return false; + } + + bool EtcObjManager::add_sphere(int32_t& index, int32_t& count, const EtcObjSphere& sphere) { + if (sphere.slices < 2 || sphere.stacks < 2) + return false; + + for (const auto& i : etc_obj_buffer) { + if (i.first.first != ETC_OBJ_SPHERE) + continue; + + const EtcObjSphere& other_sphere = i.second.sphere; + if (other_sphere.slices == sphere.slices + && other_sphere.stacks == sphere.stacks + && fabsf(other_sphere.radius - sphere.radius) < 0.00001f) { + index = i.first.second; + count = 1; + return true; + } + } + + index = (int32_t)draw_param_buffer.size(); + count = 1; + + const size_t stacks = (((size_t)sphere.stacks + 1) / 2) * 2; + const size_t slices = sphere.slices; + + etc_obj_vertex_data* vtx_data = 0; + size_t vtx_count = ((size_t)slices * ((size_t)stacks - 1) + 2); + size_t start = add_data(vtx_data, vtx_count); + + gen_sphere_vertices(vtx_data, sphere.slices, sphere.stacks, sphere.radius); + + draw_param_buffer.push_back({}); + etc_obj_draw_param& draw_param = draw_param_buffer.back(); + + draw_param.attrib.m.primitive = sphere.wire ? GL_LINES : GL_TRIANGLES; + draw_param.start = (GLuint)start; + + size_t idx_offset = index_buffer.size(); + gen_sphere_indices(index_buffer, sphere.slices, sphere.stacks, sphere.wire, start); + + draw_param.end = (GLuint)(start + vtx_count - 1); + draw_param.offset = (GLintptr)(idx_offset * sizeof(uint32_t)); + draw_param.count = (GLsizei)(index_buffer.size() - idx_offset); + + etc_obj_buffer.push_back({ ETC_OBJ_SPHERE, index }, sphere); + return true; + } + + void EtcObjManager::clear() { + draw_param_buffer.clear(); + vertex_buffer.clear(); + index_buffer.clear(); + etc_obj_buffer.clear(); + } + + void EtcObjManager::pre_draw() { + update(); + } + + void EtcObjManager::post_draw() { + clear(); + } + + void EtcObjManager::update() { + static const GLsizei buffer_size = sizeof(etc_obj_vertex_data); + + if (vbo_vertex_count < vertex_buffer.size() / buffer_size) { + while (vbo_vertex_count < vertex_buffer.size() / buffer_size) + vbo_vertex_count *= 2; + + vbo.Recreate(gl_state, buffer_size * vbo_vertex_count); + + gl_state.bind_vertex_array(vao); + gl_state.bind_array_buffer(vbo, true); + + set_default_vertex_attrib(); + + glEnableVertexAttribArray(POSITION_INDEX); + glVertexAttribPointer(POSITION_INDEX, 3, GL_FLOAT, GL_FALSE, buffer_size, + (void*)offsetof(etc_obj_vertex_data, position)); + glEnableVertexAttribArray(NORMAL_INDEX); + glVertexAttribPointer(NORMAL_INDEX, 3, GL_FLOAT, GL_FALSE, buffer_size, + (void*)offsetof(etc_obj_vertex_data, normal)); + + gl_state.bind_array_buffer(0); + gl_state.bind_vertex_array(0); + } + + vbo.WriteMemory(gl_state, 0, vertex_buffer.size(), vertex_buffer.data()); + + if (ebo_index_count < index_buffer.size()) { + while (ebo_index_count < index_buffer.size()) + ebo_index_count *= 2; + + ebo.Recreate(gl_state, sizeof(uint32_t) * ebo_index_count); + + gl_state.bind_vertex_array(vao); + gl_state.bind_element_array_buffer(ebo, true); + + gl_state.bind_vertex_array(0); + gl_state.bind_element_array_buffer(0); + } + + ebo.WriteMemory(gl_state, 0, sizeof(uint32_t) * index_buffer.size(), index_buffer.data()); + + gl_state.bind_array_buffer(0); + gl_state.bind_element_array_buffer(0); + } + void DispManager::vertex_array::reset_vertex_attrib() { alive_time = 0; vertex_buffer = 0; @@ -335,14 +1100,6 @@ namespace mdl { glDeleteVertexArrays(1, &i.vertex_array); vertex_array_cache.clear(); - for (DispManager::etc_vertex_array& i : etc_vertex_array_cache) { - glDeleteVertexArrays(1, &i.vertex_array); - - i.vertex_buffer.Destroy(); - i.index_buffer.Destroy(); - } - etc_vertex_array_cache.clear(); - free_def(buff); } @@ -419,22 +1176,7 @@ namespace mdl { glGenVertexArrays(1, &vertex_array->vertex_array); gl_state.bind_vertex_array(vertex_array->vertex_array, true); - glVertexAttrib4f( POSITION_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); - glVertexAttrib4f( BONE_WEIGHT_INDEX, 0.0f, 0.0f, 0.0f, 0.0f); - glVertexAttrib4f( NORMAL_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); - glVertexAttrib4f( COLOR0_INDEX, 1.0f, 1.0f, 1.0f, 1.0f); - glVertexAttrib4f( COLOR1_INDEX, 1.0f, 1.0f, 1.0f, 1.0f); - glVertexAttrib4f( MORPH_COLOR_INDEX, 1.0f, 1.0f, 1.0f, 1.0f); - glVertexAttrib4f( TANGENT_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); - glVertexAttrib4f( UNKNOWN_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); - glVertexAttrib4f( TEXCOORD0_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); - glVertexAttrib4f( TEXCOORD1_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); - glVertexAttrib4f( MORPH_POSITION_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); - glVertexAttrib4f( MORPH_NORMAL_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); - glVertexAttrib4f( MORPH_TANGENT_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); - glVertexAttrib4f(MORPH_TEXCOORD0_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); - glVertexAttrib4f(MORPH_TEXCOORD1_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); - glVertexAttrib4f( BONE_INDEX_INDEX, 0.0f, 0.0f, 0.0f, 0.0f); + set_default_vertex_attrib(); new_vertex_array = true; } @@ -930,940 +1672,6 @@ namespace mdl { gl_state.bind_element_array_buffer(0); } - static size_t gen_grid_vertices(std::vector>& data, - int32_t w, int32_t h, int32_t ws, int32_t hs) { - const int32_t ws_half = ws / 2; - const int32_t hs_half = hs / 2; - const float_t w_flt = (float_t)w; - const float_t h_flt = (float_t)h; - - const float_t width = w_flt * 0.5f; - const float_t height = h_flt * 0.5f; - - data.reserve(ws * 2ULL); - for (int32_t i = 0; i <= ws; i++) { - if (i == ws_half) - continue; - - const float_t w = (float_t)i * (w_flt / ((float_t)ws_half * 2.0f)) - width; - data.push_back({ { w, 0.0f, -height }, { 0.0f } }); - data.push_back({ { w, 0.0f, height }, { 0.0f } }); - } - - data.reserve(hs * 2ULL); - for (int32_t i = 0; i <= hs; i++) { - if (i == hs_half) - continue; - - const float_t h = (float_t)i * (h_flt / ((float_t)hs_half * 2.0f)) - height; - data.push_back({ { -width, 0.0f, h }, { 0.0f } }); - data.push_back({ { width, 0.0f, h }, { 0.0f } }); - } - - size_t center_offset = data.size(); - - data.reserve(2 * 2ULL); - data.push_back({ { 0.0f, 0.0f, -height }, { 0.0f } }); - data.push_back({ { 0.0f, 0.0f, height }, { 0.0f } }); - data.push_back({ { -width, 0.0f, 0.0f }, { 0.0f } }); - data.push_back({ { width, 0.0f, 0.0f }, { 0.0f } }); - - return center_offset; - } - - static void gen_cube_vertices(std::vector>& data, vec3 size) { - size *= 0.5f; - - data.reserve(4 * 6ULL); - - data.push_back({ { -size.x, -size.y, -size.z }, { 0.0f, 0.0f, -1.0f } }); - data.push_back({ { size.x, size.y, -size.z }, { 0.0f, 0.0f, -1.0f } }); - data.push_back({ { size.x, -size.y, -size.z }, { 0.0f, 0.0f, -1.0f } }); - data.push_back({ { -size.x, size.y, -size.z }, { 0.0f, 0.0f, -1.0f } }); - - data.push_back({ { -size.x, -size.y, size.z }, { 0.0f, 0.0f, 1.0f } }); - data.push_back({ { size.x, -size.y, size.z }, { 0.0f, 0.0f, 1.0f } }); - data.push_back({ { size.x, size.y, size.z }, { 0.0f, 0.0f, 1.0f } }); - data.push_back({ { -size.x, size.y, size.z }, { 0.0f, 0.0f, 1.0f } }); - - data.push_back({ { -size.x, size.y, size.z }, { -1.0f, 0.0f, 0.0f } }); - data.push_back({ { -size.x, size.y, -size.z }, { -1.0f, 0.0f, 0.0f } }); - data.push_back({ { -size.x, -size.y, -size.z }, { -1.0f, 0.0f, 0.0f } }); - data.push_back({ { -size.x, -size.y, size.z }, { -1.0f, 0.0f, 0.0f } }); - - data.push_back({ { size.x, size.y, -size.z }, { 1.0f, 0.0f, 0.0f } }); - data.push_back({ { size.x, size.y, size.z }, { 1.0f, 0.0f, 0.0f } }); - data.push_back({ { size.x, -size.y, -size.z }, { 1.0f, 0.0f, 0.0f } }); - data.push_back({ { size.x, -size.y, size.z }, { 1.0f, 0.0f, 0.0f } }); - - data.push_back({ { -size.x, -size.y, -size.z }, { 0.0f, -1.0f, 0.0f } }); - data.push_back({ { size.x, -size.y, -size.z }, { 0.0f, -1.0f, 0.0f } }); - data.push_back({ { size.x, -size.y, size.z }, { 0.0f, -1.0f, 0.0f } }); - data.push_back({ { -size.x, -size.y, size.z }, { 0.0f, -1.0f, 0.0f } }); - - data.push_back({ { -size.x, size.y, -size.z }, { 0.0f, 1.0f, 0.0f } }); - data.push_back({ { size.x, size.y, size.z }, { 0.0f, 1.0f, 0.0f } }); - data.push_back({ { size.x, size.y, -size.z }, { 0.0f, 1.0f, 0.0f } }); - data.push_back({ { -size.x, size.y, size.z }, { 0.0f, 1.0f, 0.0f } }); - } - - static size_t gen_cube_indices(std::vector& indices) { - const uint32_t sides_indices[] = { - 0, 1, 2, 0, 3, 1, - 4, 5, 6, 6, 7, 4, - 8, 9, 10, 10, 11, 8, - 12, 13, 14, 15, 14, 13, - 16, 17, 18, 18, 19, 16, - 20, 21, 22, 20, 23, 21, - }; - - const uint32_t edges_indices[] = { - 0, 2, 1, 2, 0, 3, 1, 3, - 4, 5, 6, 5, 4, 7, 6, 7, - 0, 4, 1, 6, 2, 5, 3, 7, - }; - - indices.insert(indices.end(), sides_indices, - sides_indices + sizeof(sides_indices) / sizeof(uint32_t)); - - size_t wire_offset = indices.size(); - - indices.insert(indices.end(), edges_indices, - edges_indices + sizeof(edges_indices) / sizeof(uint32_t)); - - return wire_offset; - } - - static void gen_sphere_vertices(std::vector>& data, - int32_t slices, int32_t stacks, float_t radius) { - if (slices < 2 || stacks < 2) - return; - - data.push_back({ { 0.0f, radius, 0.0f }, { 0.0f, -1.0f, 0.0f} }); - - double_t slice_step = (M_PI * 2.0) / (double_t)slices; - double_t stack_step = M_PI / (double_t)stacks; - - for (int32_t i = 1; i < stacks; i++) { - float_t stack_angle = (float_t)((M_PI / 2.0) - (double_t)i * stack_step); - float_t xz = cosf(stack_angle); - float_t y = sinf(stack_angle); - - data.reserve(slices); - - for (int32_t j = 0; j < slices; j++) { - float_t slice_angle = (float_t)((double_t)j * slice_step); - - float_t x = xz * cosf(slice_angle); - float_t z = xz * sinf(slice_angle); - - data.push_back({ { x * radius, y * radius, z * radius }, { x, y, z } }); - } - } - - data.push_back({ { 0.0f, -radius, 0.0f }, { 0.0f, -1.0f, 0.0f} }); - } - - static size_t gen_sphere_indices(std::vector& indices, - int32_t slices, int32_t stacks) { - if (slices < 2 || stacks < 2) - return 0; - - // Top stack vertices - { - int32_t m1 = 0; - int32_t m2 = 1; - - indices.reserve(3LL * slices); - - for (int32_t j = 0, k = 1; j < slices; j++) { - indices.push_back(m1); - indices.push_back(k + m2); - indices.push_back(j + m2); - - if (++k >= slices) - k = 0; - } - } - - // Middle stacks vertices - for (int32_t i = 1; i < stacks - 1; i++) { - int32_t m1 = (i - 1) * slices + 1; - int32_t m2 = m1 + slices; - - indices.reserve(6LL * slices); - - for (int32_t j = 0, k = 1; j < slices; j++) { - indices.push_back(j + m1); - indices.push_back(k + m1); - indices.push_back(j + m2); - - indices.push_back(k + m1); - indices.push_back(k + m2); - indices.push_back(j + m2); - - if (++k >= slices) - k = 0; - } - } - - // Bottom stack vertices - { - int32_t m1 = (stacks - 2) * slices + 1; - int32_t m2 = m1 + slices; - - indices.reserve(3LL * slices); - - for (int32_t j = 0, k = 1; j < slices; j++) { - indices.push_back(j + m1); - indices.push_back(k + m1); - indices.push_back(m2); - - if (++k >= slices) - k = 0; - } - } - - size_t wire_offset = indices.size(); - - // Top stack wireframe - { - int32_t m1 = 0; - int32_t m2 = 1; - - indices.reserve(2LL * slices); - - for (int32_t j = 0; j < slices; j++) { - indices.push_back(m1); - indices.push_back(j + m2); - } - } - - // Middle stacks wireframe - for (int32_t i = 1; i < stacks - 1; i++) { - int32_t m1 = (i - 1) * slices + 1; - int32_t m2 = m1 + slices; - - indices.reserve(2LL * slices); - - for (int32_t j = 0; j < slices; j++) { - indices.push_back(j + m1); - indices.push_back(j + m2); - } - } - - // Bottom stack wireframe - { - int32_t m1 = (stacks - 2) * slices + 1; - int32_t m2 = m1 + slices; - - indices.reserve(2LL * slices); - - for (int32_t j = 0; j < slices; j++) { - indices.push_back(j + m1); - indices.push_back(m2); - } - } - - // Slices wireframe - for (int32_t i = 1; i < stacks; i++) { - int32_t m = (i - 1) * slices + 1; - - indices.reserve(2LL * slices); - - for (int32_t j = 0, k = 1; j < slices; j++) { - indices.push_back(j + m); - indices.push_back(k + m); - - if (++k >= slices) - k = 0; - } - } - - return wire_offset; - } - - static void gen_plane_vertices(std::vector>& data, int32_t w, int32_t h) { - float_t width = (float_t)w * 0.5f; - float_t height = (float_t)h * 0.5f; - - data.reserve(4); - - data.push_back({ { width, 0.0f, height }, { 0.0f, 1.0f, 0.0f } }); - data.push_back({ { width, 0.0f, -height }, { 0.0f, 1.0f, 0.0f } }); - data.push_back({ { -width, 0.0f, height }, { 0.0f, 1.0f, 0.0f } }); - data.push_back({ { -width, 0.0f, -height }, { 0.0f, 1.0f, 0.0f } }); - } - - static void gen_line_vertices(std::vector>& data, float_t length) { - length *= 0.5f; - - data.reserve(2); - - data.push_back({ { 0.0f, length, 0.0f }, { 0.0f } }); - data.push_back({ { 0.0f, -length, 0.0f }, { 0.0f } }); - } - - static void gen_cross_vertices(std::vector>& data, float_t size) { - data.reserve(6); - - data.push_back({ { -size, 0.0f, 0.0f }, { 0.0f } }); - data.push_back({ { size, 0.0f, 0.0f }, { 0.0f } }); - data.push_back({ { 0.0f, -size, 0.0f }, { 0.0f } }); - data.push_back({ { 0.0f, size, 0.0f }, { 0.0f } }); - data.push_back({ { 0.0f, 0.0f, -size }, { 0.0f } }); - data.push_back({ { 0.0f, 0.0f, size }, { 0.0f } }); - } - - static void gen_capsule_vertices(std::vector>& data, - int32_t slices, int32_t stacks, float_t length, float_t radius) { - if (slices < 2 || stacks < 2) - return; - - stacks = ((stacks + 1) >> 1) << 1; - - if (length < 0.00001f) { - gen_sphere_vertices(data, slices, stacks, radius); - return; - } - - length *= 0.5f; - - data.push_back({ { 0.0f, radius + length, 0.0f }, { 0.0f, 1.0f, 0.0f } }); - - double_t slice_step = (M_PI * 2.0) / (double_t)slices; - double_t stack_step = M_PI / (double_t)stacks; - - for (int32_t i = 1; i <= stacks / 2; i++) { - float_t stack_angle = (float_t)((M_PI / 2.0) - (double_t)i * stack_step); - float_t xz = cosf(stack_angle); - float_t y = sinf(stack_angle); - y *= radius; - - data.reserve(slices); - - for (int32_t j = 0; j < slices; j++) { - float_t slice_angle = (float_t)((double_t)j * slice_step); - - float_t x = xz * cosf(slice_angle); - float_t z = xz * sinf(slice_angle); - - data.push_back({ { x * radius, y + length, z * radius }, { x, y, z } }); - } - } - - for (int32_t i = stacks / 2; i < stacks; i++) { - float_t stack_angle = (float_t)((M_PI / 2.0) - (double_t)i * stack_step); - float_t xz = cosf(stack_angle); - float_t y = sinf(stack_angle); - y *= radius; - - data.reserve(slices); - - for (int32_t j = 0; j < slices; j++) { - float_t slice_angle = (float_t)((double_t)j * slice_step); - - float_t x = xz * cosf(slice_angle); - float_t z = xz * sinf(slice_angle); - - data.push_back({ { x * radius, y - length, z * radius }, { x, y, z } }); - } - } - - data.push_back({ { 0.0f, -radius - length, 0.0f }, { 0.0f, -1.0f, 0.0f } }); - } - - static size_t gen_capsule_indices(std::vector& indices, - int32_t slices, int32_t stacks, float_t length) { - if (slices < 2 || stacks < 2) - return 0; - - stacks = ((stacks + 1) >> 1) << 1; - - if (length < 0.00001f) - return gen_sphere_indices(indices, slices, stacks); - - // Top stack vertices - { - int32_t m1 = 0; - int32_t m2 = 1; - - indices.reserve(3LL * slices); - - for (int32_t j = 0, k = 1; j < slices; j++) { - indices.push_back(m1); - indices.push_back(k + m2); - indices.push_back(j + m2); - - if (++k >= slices) - k = 0; - } - } - - // Middle stacks vertices - for (int32_t i = 1; i < stacks; i++) { - int32_t m1 = (i - 1) * slices + 1; - int32_t m2 = m1 + slices; - - indices.reserve(6LL * slices); - - for (int32_t j = 0, k = 1; j < slices; j++) { - indices.push_back(j + m1); - indices.push_back(k + m1); - indices.push_back(j + m2); - - indices.push_back(k + m1); - indices.push_back(k + m2); - indices.push_back(j + m2); - - if (++k >= slices) - k = 0; - } - } - - // Bottom stack vertices - { - int32_t m1 = (stacks - 1) * slices + 1; - int32_t m2 = m1 + slices; - - indices.reserve(3LL * slices); - - for (int32_t j = 0, k = 1; j < slices; j++) { - indices.push_back(j + m1); - indices.push_back(k + m1); - indices.push_back(m2); - - if (++k >= slices) - k = 0; - } - } - - size_t wire_offset = indices.size(); - - // Top stack wireframe - { - int32_t m1 = 0; - int32_t m2 = 1; - - indices.reserve(2LL * slices); - - for (int32_t j = 0; j < slices; j++) { - indices.push_back(m1); - indices.push_back(j + m2); - } - } - - // Middle stacks wireframe - for (int32_t i = 1; i < stacks; i++) { - int32_t m1 = (i - 1) * slices + 1; - int32_t m2 = m1 + slices; - - indices.reserve(2LL * slices); - - for (int32_t j = 0; j < slices; j++) { - indices.push_back(j + m1); - indices.push_back(j + m2); - } - } - - // Bottom stack wireframe - { - int32_t m1 = (stacks - 1) * slices + 1; - int32_t m2 = m1 + slices; - - indices.reserve(2LL * slices); - - for (int32_t j = 0; j < slices; j++) { - indices.push_back(j + m1); - indices.push_back(m2); - } - } - - // Slices wireframe - for (int32_t i = 1; i <= stacks; i++) { - int32_t m = (i - 1) * slices + 1; - - indices.reserve(2LL * slices); - - for (int32_t j = 0, k = 1; j < slices; j++) { - indices.push_back(j + m); - indices.push_back(k + m); - - if (k++ >= slices) - k = 0; - } - } - - return wire_offset; - } - - static void gen_cylinder_vertices(std::vector>& data, - int32_t slices, int32_t stacks, float_t base, float_t height) { - float_t half_height = height * 0.5f; - - if (slices < 2 || stacks < 0) - return; - - data.push_back({ { 0.0f, stacks ? half_height : 0.0f, 0.0f }, { 0.0f, 1.0f, 0.0f } }); - - double_t slice_step = (M_PI * 2.0) / (double_t)slices; - double_t stack_step = M_PI / (double_t)stacks; - - for (int32_t i = 0; i <= stacks; i++) { - float_t y = stacks ? lerp_def(half_height, -half_height, (float_t)i / (float_t)stacks) : 0.0f; - - data.reserve(slices); - - for (int32_t j = 0; j < slices; j++) { - float_t slice_angle = (float_t)((double_t)j * slice_step); - - float_t x = cosf(slice_angle); - float_t z = sinf(slice_angle); - - data.push_back({ { x * base, y, z * base }, { x, 0.0f, z } }); - } - } - - data.push_back({ { 0.0f, stacks ? -half_height : 0.0f, 0.0f }, { 0.0f, -1.0f, 0.0f } }); - } - - static size_t gen_cylinder_indices(std::vector& indices, - int32_t slices, int32_t stacks) { - if (slices < 2 || stacks < 0) - return 0; - - // Top cap vertices - { - int32_t m1 = 0; - int32_t m2 = 1; - - indices.reserve(3LL * slices); - - for (int32_t j = 0, k = 1; j < slices; j++) { - indices.push_back(m1); - indices.push_back(k + m2); - indices.push_back(j + m2); - - if (++k >= slices) - k = 0; - } - } - - // Stacks vertices - for (int32_t i = 0; i < stacks; i++) { - int32_t m1 = i * slices + 1; - int32_t m2 = m1 + slices; - - indices.reserve(6LL * slices); - - for (int32_t j = 0, k = 1; j < slices; j++) { - indices.push_back(j + m1); - indices.push_back(k + m1); - indices.push_back(j + m2); - - indices.push_back(k + m1); - indices.push_back(k + m2); - indices.push_back(j + m2); - - if (++k >= slices) - k = 0; - } - } - - // Bottom cap vertices - { - int32_t m1 = stacks * slices + 1; - int32_t m2 = m1 + slices; - - indices.reserve(3LL * slices); - - for (int32_t j = 0, k = 1; j < slices; j++) { - indices.push_back(j + m1); - indices.push_back(k + m1); - indices.push_back(m2); - - if (++k >= slices) - k = 0; - } - } - - size_t wire_offset = indices.size(); - - // Stacks wireframe - for (int32_t i = 0; i < stacks; i++) { - int32_t m1 = i * slices + 1; - int32_t m2 = m1 + slices; - - indices.reserve(2LL * slices); - - for (int32_t j = 0; j < slices; j++) { - indices.push_back(j + m1); - indices.push_back(j + m2); - } - } - - // Slices wireframe - for (int32_t i = 0; i <= stacks; i++) { - int32_t m = i * slices + 1; - - indices.reserve(2LL * slices); - - for (int32_t j = 0, k = 1; j < slices; j++) { - indices.push_back(j + m); - indices.push_back(k + m); - - if (k++ >= slices) - k = 0; - } - } - - return wire_offset; - } - - void DispManager::add_vertex_array(EtcObj* etc, mat4& mat) { - EtcObjType type = etc->type; - switch (type) { - case mdl::ETC_OBJ_TEAPOT: - case mdl::ETC_OBJ_GRID: - case mdl::ETC_OBJ_CUBE: - case mdl::ETC_OBJ_SPHERE: - case mdl::ETC_OBJ_PLANE: - case mdl::ETC_OBJ_CONE: - case mdl::ETC_OBJ_LINE: - case mdl::ETC_OBJ_CROSS: - case mdl::ETC_OBJ_CAPSULE: // Added - case mdl::ETC_OBJ_CYLINDER: // Added - break; - default: - return; - } - - bool indexed = false; - bool wire = false; - float_t length = 0.0f; - - switch (type) { - case mdl::ETC_OBJ_TEAPOT: { - EtcObjTeapot& teapot = etc->data.teapot; - - indexed = true; - } break; - case mdl::ETC_OBJ_GRID: { - EtcObjGrid& grid = etc->data.grid; - - } break; - case mdl::ETC_OBJ_CUBE: { - EtcObjCube& cube = etc->data.cube; - - indexed = true; - wire = cube.wire; - } break; - case mdl::ETC_OBJ_SPHERE: { - EtcObjSphere& sphere = etc->data.sphere; - - indexed = true; - wire = sphere.wire; - } break; - case mdl::ETC_OBJ_PLANE: { - EtcObjPlane& plane = etc->data.plane; - } break; - case mdl::ETC_OBJ_CONE: { - EtcObjCone& cone = etc->data.cone; - - indexed = true; - wire = cone.wire; - } break; - case mdl::ETC_OBJ_LINE: { - EtcObjLine& line = etc->data.line; - - vec3 origin = (line.pos[0] + line.pos[1]) * 0.5f; - mat4_add_translate(&mat, &origin, &mat); - - const vec3 dir = vec3::normalize(line.pos[1] - line.pos[0]); - const vec3 up = { 0.0f, 1.0f, 0.0f }; - vec3 axis; - float_t angle; - vec3::axis_angle_from_vectors(axis, angle, up, dir); - - mat4 m = mat4_identity; - mat4_mul_rotation(&m, &axis, angle, &m); - mat4_mul(&m, &mat, &mat); - - length = vec3::distance(line.pos[0], line.pos[1]); - } break; - case mdl::ETC_OBJ_CROSS: { - EtcObjCross& cross = etc->data.cross; - } break; - case mdl::ETC_OBJ_CAPSULE: { // Added - EtcObjCapsule& capsule = etc->data.capsule; - - vec3 origin = (capsule.pos[0] + capsule.pos[1]) * 0.5f; - mat4_add_translate(&mat, &origin, &mat); - - const vec3 dir = vec3::normalize(capsule.pos[1] - capsule.pos[0]); - const vec3 up = { 0.0f, 1.0f, 0.0f }; - vec3 axis; - float_t angle; - vec3::axis_angle_from_vectors(axis, angle, up, dir); - - mat4 m = mat4_identity; - mat4_mul_rotation(&m, &axis, angle, &m); - mat4_mul(&m, &mat, &mat); - - indexed = true; - wire = capsule.wire; - length = vec3::distance(capsule.pos[0], capsule.pos[1]); - } break; - case mdl::ETC_OBJ_CYLINDER: { // Added - EtcObjCylinder& cylinder = etc->data.cylinder; - - indexed = true; - wire = cylinder.wire; - } break; - } - - DispManager::etc_vertex_array* etc_vertex_array = 0; - for (DispManager::etc_vertex_array& i : etc_vertex_array_cache) { - if (i.alive_time <= 0 || i.type != type || i.vertex_buffer.IsNull()) - continue; - - if (type == mdl::ETC_OBJ_TEAPOT - || type == mdl::ETC_OBJ_GRID - && !memcmp(&i.data.grid, &etc->data.grid, sizeof(EtcObjGrid)) - || type == mdl::ETC_OBJ_CUBE - && vec3::dot(vec3::abs(i.data.cube.size - etc->data.cube.size), 1.0f) < 0.00001f - || type == mdl::ETC_OBJ_SPHERE - && i.data.sphere.slices == etc->data.sphere.slices - && i.data.sphere.stacks == etc->data.sphere.stacks - && fabsf(i.data.sphere.radius - etc->data.sphere.radius) < 0.00001f - || type == mdl::ETC_OBJ_PLANE - && i.data.plane.w == etc->data.plane.w - && i.data.plane.h == etc->data.plane.h - || type == mdl::ETC_OBJ_CONE - && i.data.cone.slices == etc->data.cone.slices - && i.data.cone.stacks == etc->data.cone.stacks - && fabsf(i.data.cone.base - etc->data.cone.base) < 0.00001f - && fabsf(i.data.cone.height - etc->data.cone.height) < 0.00001f - || type == mdl::ETC_OBJ_LINE - && fabsf(vec3::distance(i.data.line.pos[0], i.data.line.pos[1]) - length) < 0.00001f - || type == mdl::ETC_OBJ_CROSS - && fabsf(i.data.cross.size - etc->data.cross.size) < 0.00001f - || type == mdl::ETC_OBJ_CAPSULE // Added - && i.data.capsule.slices == etc->data.capsule.slices - && ((i.data.capsule.stacks + 1)) >> 1 == ((etc->data.capsule.stacks + 1) >> 1) - && fabsf(i.data.capsule.radius - etc->data.capsule.radius) < 0.00001f - && fabsf(vec3::distance(i.data.capsule.pos[0], i.data.capsule.pos[1]) - length) < 0.00001f - || type == mdl::ETC_OBJ_CYLINDER // Added - && i.data.cylinder.slices == etc->data.cylinder.slices - && i.data.cylinder.stacks == etc->data.cylinder.stacks - && fabsf(i.data.cylinder.base - etc->data.cylinder.base) < 0.00001f - && fabsf(i.data.cylinder.height - etc->data.cylinder.height) < 0.00001f) - if (i.vertex_array) { - i.alive_time = 2; - if (!wire) { - etc->count = i.count; - etc->offset = i.offset; - } - else { - etc->count = i.wire_count; - etc->offset = i.wire_offset; - } - return; - } - else { - etc_vertex_array = &i; - break; - } - } - - if (!etc_vertex_array) - for (DispManager::etc_vertex_array& i : etc_vertex_array_cache) - if (i.alive_time <= 0) { - etc_vertex_array = &i; - break; - } - - if (!etc_vertex_array) { - etc_vertex_array_cache.push_back({}); - etc_vertex_array = &etc_vertex_array_cache.back(); - } - - bool new_vertex_array = false; - if (!etc_vertex_array->vertex_array) { - glGenVertexArrays(1, &etc_vertex_array->vertex_array); - - gl_state.bind_vertex_array(etc_vertex_array->vertex_array); - glVertexAttrib4f( POSITION_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); - glVertexAttrib4f( BONE_WEIGHT_INDEX, 0.0f, 0.0f, 0.0f, 0.0f); - glVertexAttrib4f( NORMAL_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); - glVertexAttrib4f( COLOR0_INDEX, 1.0f, 1.0f, 1.0f, 1.0f); - glVertexAttrib4f( COLOR1_INDEX, 1.0f, 1.0f, 1.0f, 1.0f); - glVertexAttrib4f( MORPH_COLOR_INDEX, 1.0f, 1.0f, 1.0f, 1.0f); - glVertexAttrib4f( TANGENT_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); - glVertexAttrib4f( UNKNOWN_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); - glVertexAttrib4f( TEXCOORD0_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); - glVertexAttrib4f( TEXCOORD1_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); - glVertexAttrib4f( MORPH_POSITION_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); - glVertexAttrib4f( MORPH_NORMAL_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); - glVertexAttrib4f( MORPH_TANGENT_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); - glVertexAttrib4f(MORPH_TEXCOORD0_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); - glVertexAttrib4f(MORPH_TEXCOORD1_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); - glVertexAttrib4f( BONE_INDEX_INDEX, 0.0f, 0.0f, 0.0f, 0.0f); - new_vertex_array = true; - } - - etc_vertex_array->alive_time = 2; - etc_vertex_array->data = etc->data; - etc_vertex_array->type = type; - etc_vertex_array->indexed = indexed; - - std::vector> vtx_data; - std::vector vtx_indices; - switch (type) { - case mdl::ETC_OBJ_TEAPOT: { - EtcObjTeapot& teapot = etc->data.teapot; - - etc_vertex_array->count = (GLsizei)vtx_indices.size(); - } break; - case mdl::ETC_OBJ_GRID: { - EtcObjGrid& grid = etc->data.grid; - - size_t center_offset = gen_grid_vertices(vtx_data, grid.w, grid.h, grid.ws, grid.hs); - - etc_vertex_array->offset = 0; - etc_vertex_array->count = (GLsizei)center_offset; - } break; - case mdl::ETC_OBJ_CUBE: { - EtcObjCube& cube = etc->data.cube; - - gen_cube_vertices(vtx_data, cube.size); - size_t wire_offset = gen_cube_indices(vtx_indices); - - etc_vertex_array->offset = 0; - etc_vertex_array->count = (GLsizei)wire_offset; - etc_vertex_array->wire_offset = wire_offset * sizeof(uint32_t); - etc_vertex_array->wire_count = (GLsizei)(vtx_indices.size() - wire_offset); - } break; - case mdl::ETC_OBJ_SPHERE: { - EtcObjSphere& sphere = etc->data.sphere; - - gen_sphere_vertices(vtx_data, sphere.slices, sphere.stacks, sphere.radius); - size_t wire_offset = gen_sphere_indices(vtx_indices, sphere.slices, sphere.stacks); - - etc_vertex_array->offset = 0; - etc_vertex_array->count = (GLsizei)wire_offset; - etc_vertex_array->wire_offset = wire_offset * sizeof(uint32_t); - etc_vertex_array->wire_count = (GLsizei)(vtx_indices.size() - wire_offset); - } break; - case mdl::ETC_OBJ_PLANE: { - EtcObjPlane& plane = etc->data.plane; - - gen_plane_vertices(vtx_data, plane.w, plane.h); - - etc_vertex_array->count = (GLsizei)vtx_data.size(); - } break; - case mdl::ETC_OBJ_CONE: { - EtcObjCone& cone = etc->data.cone; - - etc_vertex_array->count = (GLsizei)vtx_indices.size(); - } break; - case mdl::ETC_OBJ_LINE: { - EtcObjLine& line = etc->data.line; - - gen_line_vertices(vtx_data, length); - - etc_vertex_array->count = (GLsizei)vtx_data.size(); - } break; - case mdl::ETC_OBJ_CROSS: { - EtcObjCross& cross = etc->data.cross; - - gen_cross_vertices(vtx_data, cross.size); - - etc_vertex_array->count = (GLsizei)vtx_data.size(); - } break; - case mdl::ETC_OBJ_CAPSULE: { // Added - EtcObjCapsule& capsule = etc->data.capsule; - - gen_capsule_vertices(vtx_data, capsule.slices, capsule.stacks, length, capsule.radius); - size_t wire_offset = gen_capsule_indices(vtx_indices, capsule.slices, capsule.stacks, length); - - etc_vertex_array->offset = 0; - etc_vertex_array->count = (GLsizei)wire_offset; - etc_vertex_array->wire_offset = wire_offset * sizeof(uint32_t); - etc_vertex_array->wire_count = (GLsizei)(vtx_indices.size() - wire_offset); - } break; - case mdl::ETC_OBJ_CYLINDER: { // Added - EtcObjCylinder& cylinder = etc->data.cylinder; - - gen_cylinder_vertices(vtx_data, cylinder.slices, cylinder.stacks, cylinder.base, cylinder.height); - size_t wire_offset = gen_cylinder_indices(vtx_indices, cylinder.slices, cylinder.stacks); - - etc_vertex_array->offset = 0; - etc_vertex_array->count = (GLsizei)wire_offset; - etc_vertex_array->wire_offset = wire_offset * sizeof(uint32_t); - etc_vertex_array->wire_count = (GLsizei)(vtx_indices.size() - wire_offset); - } break; - } - - if (!wire) { - etc->count = etc_vertex_array->count; - etc->offset = etc_vertex_array->offset; - } - else { - etc->count = etc_vertex_array->wire_count; - etc->offset = etc_vertex_array->wire_offset; - } - - if (!etc_vertex_array->count) - return; - - if (etc_vertex_array->max_vtx < vtx_data.size()) { - etc_vertex_array->max_vtx = vtx_data.size(); - - etc_vertex_array->vertex_buffer.Destroy(); - } - - if (etc_vertex_array->max_idx < vtx_indices.size()) { - etc_vertex_array->max_idx = vtx_indices.size(); - - etc_vertex_array->index_buffer.Destroy(); - } - - GLsizei size_vertex = sizeof(vec3) * 2; - - if (!new_vertex_array) - gl_state.bind_vertex_array(etc_vertex_array->vertex_array); - - if (etc_vertex_array->vertex_buffer.IsNull()) - etc_vertex_array->vertex_buffer.Create(gl_state, sizeof(vec3) * 2 * vtx_data.size()); - - gl_state.bind_array_buffer(etc_vertex_array->vertex_buffer, true); - glBufferSubData(GL_ARRAY_BUFFER, 0, sizeof(vec3) * 2 - * vtx_data.size(), vtx_data.data()); - - if (indexed) { - if (etc_vertex_array->index_buffer.IsNull()) - etc_vertex_array->index_buffer.Create(gl_state, sizeof(uint32_t) * vtx_indices.size()); - - gl_state.bind_element_array_buffer(etc_vertex_array->index_buffer, true); - glBufferSubData(GL_ELEMENT_ARRAY_BUFFER, 0, sizeof(uint32_t) - * vtx_indices.size(), vtx_indices.data()); - } - - glEnableVertexAttribArray(POSITION_INDEX); - glVertexAttribPointer(POSITION_INDEX, - 3, GL_FLOAT, GL_FALSE, size_vertex, (void*)0); - - glEnableVertexAttribArray(NORMAL_INDEX); - glVertexAttribPointer(NORMAL_INDEX, - 3, GL_FLOAT, GL_FALSE, size_vertex, (void*)sizeof(vec3)); - - gl_state.bind_array_buffer(0); - gl_state.bind_vertex_array(0); - if (indexed) - gl_state.bind_element_array_buffer(0); - } - void* DispManager::alloc_data(int32_t size) { if (!buff || buff_offset + size > buff_size) return 0; @@ -2070,17 +1878,6 @@ namespace mdl { i.vertex_buffer = 0; i.morph_vertex_buffer = 0; } - - for (DispManager::etc_vertex_array& i : etc_vertex_array_cache) - if (i.alive_time > 0 && --i.alive_time <= 0) { - gl_state.bind_vertex_array(i.vertex_array, true); - glDisableVertexAttribArray(POSITION_INDEX); - glDisableVertexAttribArray( NORMAL_INDEX); - gl_state.bind_array_buffer(0, true); - if (i.indexed) - gl_state.bind_element_array_buffer(0, true); - gl_state.bind_vertex_array(0); - } } void DispManager::check_vertex_buffer(GLuint buffer) { @@ -2633,8 +2430,8 @@ namespace mdl { for (int32_t i = 0; i < 6; i++) for (int32_t j = 0; j < 8; j++) { - float_t v34 = vec3::dot(*(vec3*)&v2[i], points[j]) + v2[i].w; - if (v34 > 0.0f) + float_t vtx_data = vec3::dot(*(vec3*)&v2[i], points[j]) + v2[i].w; + if (vtx_data > 0.0f) break; if (j == 7) @@ -3234,7 +3031,7 @@ namespace mdl { bool DispManager::entry_obj_by_object_info_instanced(object_info obj_info, const std::vector& instances, float_t alpha) { - return entry_obj_by_object_info_instanced(obj_info, instances, 1.0, 1.0, 1.0, alpha); + return entry_obj_by_object_info_instanced(obj_info, instances, 1.0f, 1.0f, 1.0f, alpha); } bool DispManager::entry_obj_by_object_info_instanced(object_info obj_info, @@ -3310,11 +3107,16 @@ namespace mdl { } void DispManager::entry_obj_etc(const mat4& mat, const EtcObj& etc) { + int32_t first = 0; + int32_t count = 0; + if (!rctx_ptr->etc_obj_manager->add_obj(first, count, etc)) + return; + ObjData* data = alloc_obj_data(OBJ_KIND_ETC); if (!data) return; - data->init_etc(this, mat, etc); + data->init_etc(this, mat, first, count, etc); if (etc.color.a == 0xFF) { if (obj_flags & OBJ_SHADOW) entry_list((mdl::ObjType)(OBJ_TYPE_SHADOW_CHARA + shadow_type), data); @@ -3325,11 +3127,16 @@ namespace mdl { } void DispManager::entry_obj_etc_screen(const mat4& mat, const EtcObj& etc) { + int32_t first = 0; + int32_t count = 0; + if (!rctx_ptr->etc_obj_manager->add_obj(first, count, etc)) + return; + ObjData* data = alloc_obj_data(OBJ_KIND_ETC); if (!data) return; - data->init_etc(this, mat, etc); + data->init_etc(this, mat, first, count, etc); if (etc.color.a == 0xFF) entry_list(OBJ_TYPE_SCREEN_OPAQUE, data); else @@ -3394,88 +3201,6 @@ namespace mdl { return 0; } - GLuint DispManager::get_vertex_array(const EtcObj* etc) { - EtcObjType type = etc->type; - float_t length = 0; - switch (type) { - case mdl::ETC_OBJ_TEAPOT: - case mdl::ETC_OBJ_GRID: - case mdl::ETC_OBJ_CUBE: - case mdl::ETC_OBJ_SPHERE: - case mdl::ETC_OBJ_PLANE: - case mdl::ETC_OBJ_CONE: - break; - case mdl::ETC_OBJ_LINE: - length = vec3::distance(etc->data.line.pos[0], etc->data.line.pos[1]); - break; - case mdl::ETC_OBJ_CROSS: - break; - case mdl::ETC_OBJ_CAPSULE: // Added - length = vec3::distance(etc->data.capsule.pos[0], etc->data.capsule.pos[1]); - break; - case mdl::ETC_OBJ_CYLINDER: // Added - break; - default: - return 0; - } - - for (DispManager::etc_vertex_array& i : etc_vertex_array_cache) { - if (i.alive_time <= 0 || i.type != type) - continue; - - switch (type) { - case mdl::ETC_OBJ_TEAPOT: - return i.vertex_array; - case mdl::ETC_OBJ_GRID: - if (!memcmp(&i.data.grid, &etc->data.grid, sizeof(EtcObjGrid))) - return i.vertex_array; - break; - case mdl::ETC_OBJ_CUBE: - if (vec3::dot(vec3::abs(i.data.cube.size - etc->data.cube.size), 1.0f) < 0.00001f) - return i.vertex_array; - case mdl::ETC_OBJ_SPHERE: - if (i.data.sphere.slices == etc->data.sphere.slices - && i.data.sphere.stacks == etc->data.sphere.stacks - && fabsf(i.data.sphere.radius - etc->data.sphere.radius) < 0.00001f) - return i.vertex_array; - break; - case mdl::ETC_OBJ_PLANE: - if (i.data.plane.w == etc->data.plane.w - && i.data.plane.h == etc->data.plane.h) - return i.vertex_array; - case mdl::ETC_OBJ_CONE: - if (i.data.cone.slices == etc->data.cone.slices - && i.data.cone.stacks == etc->data.cone.stacks - && fabsf(i.data.cone.base - etc->data.cone.base) < 0.00001f - && fabsf(i.data.cone.height - etc->data.cone.height) < 0.00001f) - return i.vertex_array; - break; - case mdl::ETC_OBJ_LINE: - if (fabsf(vec3::distance(i.data.line.pos[0], i.data.line.pos[1]) - length) < 0.00001f) - return i.vertex_array; - break; - case mdl::ETC_OBJ_CROSS: - if (fabsf(i.data.cross.size - etc->data.cross.size) < 0.00001f) - return i.vertex_array; - case mdl::ETC_OBJ_CAPSULE: // Added - if (i.data.capsule.slices == etc->data.capsule.slices - && ((i.data.capsule.stacks + 1)) >> 1 == ((etc->data.capsule.stacks + 1) >> 1) - && fabsf(i.data.capsule.radius - etc->data.capsule.radius) < 0.00001f - && fabsf(vec3::distance(i.data.capsule.pos[0], i.data.capsule.pos[1]) - length) < 0.00001f) - return i.vertex_array; - break; - case mdl::ETC_OBJ_CYLINDER: // Added - if (i.data.cylinder.slices == etc->data.cylinder.slices - && i.data.cylinder.stacks == etc->data.cylinder.stacks - && fabsf(i.data.cylinder.base - etc->data.cylinder.base) < 0.00001f - && fabsf(i.data.cylinder.height - etc->data.cylinder.height) < 0.00001f) - return i.vertex_array; - break; - } - } - return 0; - } - bool DispManager::get_chara_color() { return chara_color; } @@ -3761,6 +3486,456 @@ namespace mdl { void DispManager::set_wet_param(float_t value) { wet_param = value; } + + static void gen_capsule_indices(std::vector& indices, + int32_t slices, int32_t stacks, float_t length, bool wire, size_t start) { + if (slices < 2 || stacks < 2) + return; + + stacks = ((stacks + 1) / 2) * 2; + + if (length < 0.00001f) + gen_sphere_indices(indices, slices, stacks, wire, start); + + if (!wire) { + // Top stack vertices + { + int32_t m1 = 0; + int32_t m2 = 1; + + indices.reserve(3LL * slices); + + for (int32_t j = 0, k = 1; j < slices; j++) { + indices.push_back((uint32_t)(start + m1)); + indices.push_back((uint32_t)(start + j + m2)); + indices.push_back((uint32_t)(start + k + m2)); + + if (++k >= slices) + k = 0; + } + } + + // Middle stacks vertices + for (int32_t i = 1; i < stacks; i++) { + int32_t m1 = (i - 1) * slices + 1; + int32_t m2 = m1 + slices; + + indices.reserve(6LL * slices); + + for (int32_t j = 0, k = 1; j < slices; j++) { + indices.push_back((uint32_t)(start + j + m1)); + indices.push_back((uint32_t)(start + j + m2)); + indices.push_back((uint32_t)(start + k + m1)); + + indices.push_back((uint32_t)(start + k + m1)); + indices.push_back((uint32_t)(start + j + m2)); + indices.push_back((uint32_t)(start + k + m2)); + + if (++k >= slices) + k = 0; + } + } + + // Bottom stack vertices + { + int32_t m1 = (stacks - 1) * slices + 1; + int32_t m2 = m1 + slices; + + indices.reserve(3LL * slices); + + for (int32_t j = 0, k = 1; j < slices; j++) { + indices.push_back((uint32_t)(start + j + m1)); + indices.push_back((uint32_t)(start + m2)); + indices.push_back((uint32_t)(start + k + m1)); + + if (++k >= slices) + k = 0; + } + } + } + else { + // Top stack wireframe + { + int32_t m1 = 0; + int32_t m2 = 1; + + indices.reserve(2LL * slices); + + for (int32_t j = 0; j < slices; j++) { + indices.push_back((uint32_t)(start + m1)); + indices.push_back((uint32_t)(start + j + m2)); + } + } + + // Middle stacks wireframe + for (int32_t i = 1; i < stacks; i++) { + int32_t m1 = (i - 1) * slices + 1; + int32_t m2 = m1 + slices; + + indices.reserve(2LL * slices); + + for (int32_t j = 0; j < slices; j++) { + indices.push_back((uint32_t)(start + j + m1)); + indices.push_back((uint32_t)(start + j + m2)); + } + } + + // Bottom stack wireframe + { + int32_t m1 = (stacks - 1) * slices + 1; + int32_t m2 = m1 + slices; + + indices.reserve(2LL * slices); + + for (int32_t j = 0; j < slices; j++) { + indices.push_back((uint32_t)(start + j + m1)); + indices.push_back((uint32_t)(start + m2)); + } + } + + // Slices wireframe + for (int32_t i = 1; i <= stacks; i++) { + int32_t m = (i - 1) * slices + 1; + + indices.reserve(2LL * slices); + + for (int32_t j = 0, k = 1; j < slices; j++) { + indices.push_back((uint32_t)(start + j + m)); + indices.push_back((uint32_t)(start + k + m)); + + if (++k >= slices) + k = 0; + } + } + } + } + + static void gen_capsule_vertices(etc_obj_vertex_data* data, + int32_t slices, int32_t stacks, float_t length, float_t radius) { + stacks = ((stacks + 1) / 2) * 2; + + if (length < 0.00001f) + gen_sphere_vertices(data, slices, stacks, radius); + + length *= 0.5f; + + *data++ = { { 0.0f, 0.0f, radius + length }, { 0.0f, 0.0f, 1.0f } }; + + double_t slice_step = (M_PI * 2.0) / (double_t)slices; + double_t stack_step = M_PI / (double_t)stacks; + + for (int32_t i = 1; i <= stacks / 2; i++) { + float_t stack_angle = (float_t)((M_PI / 2.0) - (double_t)i * stack_step); + float_t xy = cosf(stack_angle); + float_t z = sinf(stack_angle); + z *= radius; + + for (int32_t j = 0; j < slices; j++) { + float_t slice_angle = (float_t)((double_t)j * slice_step); + + float_t x = xy * cosf(slice_angle); + float_t y = xy * sinf(slice_angle); + + *data++ = { { x * radius, y * radius, z + length }, { x, y, z } }; + } + } + + for (int32_t i = stacks / 2; i < stacks; i++) { + float_t stack_angle = (float_t)((M_PI / 2.0) - (double_t)i * stack_step); + float_t xy = cosf(stack_angle); + float_t z = sinf(stack_angle); + z *= radius; + + for (int32_t j = 0; j < slices; j++) { + float_t slice_angle = (float_t)((double_t)j * slice_step); + + float_t x = xy * cosf(slice_angle); + float_t y = xy * sinf(slice_angle); + + *data++ = { { x * radius, y * radius, z - length }, { x, y, z } }; + } + } + + *data++ = { { 0.0f, 0.0f, -radius - length }, { 0.0f, 0.0f, -1.0f } }; + } + + static void gen_cylinder_indices(std::vector& indices, + int32_t slices, int32_t stacks, bool wire, size_t start) { + if (slices < 2 || stacks < 0) + return; + + if (!wire) { + // Top cap vertices + { + int32_t m1 = 0; + int32_t m2 = 1; + + indices.reserve(3LL * slices); + + for (int32_t j = 0, k = 1; j < slices; j++) { + indices.push_back((uint32_t)(start + m1)); + indices.push_back((uint32_t)(start + j + m2)); + indices.push_back((uint32_t)(start + k + m2)); + + if (++k >= slices) + k = 0; + } + } + + // Stacks vertices + for (int32_t i = 0; i < stacks; i++) { + int32_t m1 = i * slices + 1; + int32_t m2 = m1 + slices; + + indices.reserve(6LL * slices); + + for (int32_t j = 0, k = 1; j < slices; j++) { + indices.push_back((uint32_t)(start + j + m1)); + indices.push_back((uint32_t)(start + j + m2)); + indices.push_back((uint32_t)(start + k + m1)); + + indices.push_back((uint32_t)(start + k + m1)); + indices.push_back((uint32_t)(start + j + m2)); + indices.push_back((uint32_t)(start + k + m2)); + + if (++k >= slices) + k = 0; + } + } + + // Bottom cap vertices + { + int32_t m1 = stacks * slices + 1; + int32_t m2 = m1 + slices; + + indices.reserve(3LL * slices); + + for (int32_t j = 0, k = 1; j < slices; j++) { + indices.push_back((uint32_t)(start + j + m1)); + indices.push_back((uint32_t)(start + m2)); + indices.push_back((uint32_t)(start + k + m1)); + + if (++k >= slices) + k = 0; + } + } + } + else { + // Stacks wireframe + for (int32_t i = 0; i < stacks; i++) { + int32_t m1 = i * slices + 1; + int32_t m2 = m1 + slices; + + indices.reserve(2LL * slices); + + for (int32_t j = 0; j < slices; j++) { + indices.push_back((uint32_t)(start + j + m1)); + indices.push_back((uint32_t)(start + j + m2)); + } + } + + // Slices wireframe + for (int32_t i = 0; i <= stacks; i++) { + int32_t m = i * slices + 1; + + indices.reserve(2LL * slices); + + for (int32_t j = 0, k = 1; j < slices; j++) { + indices.push_back((uint32_t)(start + j + m)); + indices.push_back((uint32_t)(start + k + m)); + + if (++k >= slices) + k = 0; + } + } + } + } + + static void gen_cylinder_vertices(etc_obj_vertex_data* data, + int32_t slices, int32_t stacks, float_t base, float_t height) { + float_t half_height = height * 0.5f; + + *data++ = { { 0.0f, 0.0f, stacks ? half_height : 0.0f }, { 0.0f, 1.0f, 0.0f } }; + + double_t slice_step = (M_PI * 2.0) / (double_t)slices; + + for (int32_t i = 0; i <= stacks; i++) { + float_t z = stacks ? lerp_def(half_height, -half_height, (float_t)i / (float_t)stacks) : 0.0f; + + for (int32_t j = 0; j < slices; j++) { + float_t slice_angle = (float_t)((double_t)j * slice_step); + + float_t x = cosf(slice_angle); + float_t y = sinf(slice_angle); + + *data++ = { { x * base, y * base, z }, { x, y, 0.0f } }; + } + } + + *data++ = { { 0.0f, 0.0f, stacks ? -half_height : 0.0f }, { 0.0f, -1.0f, 0.0f } }; + } + + static void gen_sphere_indices(std::vector& indices, + int32_t slices, int32_t stacks, bool wire, size_t start) { + if (slices < 2 || stacks < 2) + return; + + if (!wire) { + // Top stack vertices + { + int32_t m1 = 0; + int32_t m2 = 1; + + indices.reserve(3LL * slices); + + for (int32_t j = 0, k = 1; j < slices; j++) { + indices.push_back((uint32_t)(start + m1)); + indices.push_back((uint32_t)(start + k + m2)); + indices.push_back((uint32_t)(start + j + m2)); + + if (++k >= slices) + k = 0; + } + } + + // Middle stacks vertices + for (int32_t i = 1; i < stacks - 1; i++) { + int32_t m1 = (i - 1) * slices + 1; + int32_t m2 = m1 + slices; + + indices.reserve(6LL * slices); + + for (int32_t j = 0, k = 1; j < slices; j++) { + indices.push_back((uint32_t)(start + j + m1)); + indices.push_back((uint32_t)(start + k + m1)); + indices.push_back((uint32_t)(start + j + m2)); + + indices.push_back((uint32_t)(start + k + m1)); + indices.push_back((uint32_t)(start + k + m2)); + indices.push_back((uint32_t)(start + j + m2)); + + if (++k >= slices) + k = 0; + } + } + + // Bottom stack vertices + { + int32_t m1 = (stacks - 2) * slices + 1; + int32_t m2 = m1 + slices; + + indices.reserve(3LL * slices); + + for (int32_t j = 0, k = 1; j < slices; j++) { + indices.push_back((uint32_t)(start + j + m1)); + indices.push_back((uint32_t)(start + k + m1)); + indices.push_back((uint32_t)(start + m2)); + + if (++k >= slices) + k = 0; + } + } + } + else { + // Top stack wireframe + { + int32_t m1 = 0; + int32_t m2 = 1; + + indices.reserve(2LL * slices); + + for (int32_t j = 0; j < slices; j++) { + indices.push_back((uint32_t)(start + m1)); + indices.push_back((uint32_t)(start + j + m2)); + } + } + + // Middle stacks wireframe + for (int32_t i = 1; i < stacks - 1; i++) { + int32_t m1 = (i - 1) * slices + 1; + int32_t m2 = m1 + slices; + + indices.reserve(2LL * slices); + + for (int32_t j = 0; j < slices; j++) { + indices.push_back((uint32_t)(start + j + m1)); + indices.push_back((uint32_t)(start + j + m2)); + } + } + + // Bottom stack wireframe + { + int32_t m1 = (stacks - 2) * slices + 1; + int32_t m2 = m1 + slices; + + indices.reserve(2LL * slices); + + for (int32_t j = 0; j < slices; j++) { + indices.push_back((uint32_t)(start + j + m1)); + indices.push_back((uint32_t)(start + m2)); + } + } + + // Slices wireframe + for (int32_t i = 1; i < stacks; i++) { + int32_t m = (i - 1) * slices + 1; + + indices.reserve(2LL * slices); + + for (int32_t j = 0, k = 1; j < slices; j++) { + indices.push_back((uint32_t)(start + j + m)); + indices.push_back((uint32_t)(start + k + m)); + + if (++k >= slices) + k = 0; + } + } + } + } + + static void gen_sphere_vertices(etc_obj_vertex_data* data, + int32_t slices, int32_t stacks, float_t radius) { + *data++ = { { 0.0f, 0.0f, radius }, { 0.0f, 0.0f, -1.0f } }; + + double_t slice_step = (M_PI * 2.0) / (double_t)slices; + double_t stack_step = M_PI / (double_t)stacks; + + for (int32_t i = 1; i < stacks; i++) { + float_t stack_angle = (float_t)((M_PI / 2.0) - (double_t)i * stack_step); + float_t xy = cosf(stack_angle); + float_t z = sinf(stack_angle); + + for (int32_t j = 0; j < slices; j++) { + float_t slice_angle = -(float_t)((double_t)j * slice_step); + + float_t x = xy * cosf(slice_angle); + float_t y = xy * sinf(slice_angle); + + *data++ = { { x * radius, y * radius, z * radius }, { x, y, z } }; + } + } + + *data++ = { { 0.0f, 0.0f, -radius }, { 0.0f, 0.0f, -1.0f } }; + } + + inline static void set_default_vertex_attrib() { + glVertexAttrib4f( POSITION_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); + glVertexAttrib4f( BONE_WEIGHT_INDEX, 0.0f, 0.0f, 0.0f, 0.0f); + glVertexAttrib4f( NORMAL_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); + glVertexAttrib4f( COLOR0_INDEX, 1.0f, 1.0f, 1.0f, 1.0f); + glVertexAttrib4f( COLOR1_INDEX, 1.0f, 1.0f, 1.0f, 1.0f); + glVertexAttrib4f( MORPH_COLOR_INDEX, 1.0f, 1.0f, 1.0f, 1.0f); + glVertexAttrib4f( TANGENT_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); + glVertexAttrib4f( UNKNOWN_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); + glVertexAttrib4f( TEXCOORD0_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); + glVertexAttrib4f( TEXCOORD1_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); + glVertexAttrib4f( MORPH_POSITION_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); + glVertexAttrib4f( MORPH_NORMAL_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); + glVertexAttrib4f( MORPH_TANGENT_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); + glVertexAttrib4f(MORPH_TEXCOORD0_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); + glVertexAttrib4f(MORPH_TEXCOORD1_INDEX, 0.0f, 0.0f, 0.0f, 1.0f); + glVertexAttrib4f( BONE_INDEX_INDEX, 0.0f, 0.0f, 0.0f, 0.0f); + } } static void object_data_get_vertex_attrib_buffer_bindings(const mdl::ObjSubMeshArgs* args, diff --git a/src/CRE/mdl/disp_manager.hpp b/src/CRE/mdl/disp_manager.hpp index 43169840..633d52e5 100644 --- a/src/CRE/mdl/disp_manager.hpp +++ b/src/CRE/mdl/disp_manager.hpp @@ -312,19 +312,34 @@ namespace mdl { EtcObjCylinder cylinder; // Added Data(); + Data(const EtcObjTeapot& other); + Data(const EtcObjGrid& other); + Data(const EtcObjCube& other); + Data(const EtcObjSphere& other); + Data(const EtcObjPlane& other); + Data(const EtcObjCone& other); + Data(const EtcObjLine& other); + Data(const EtcObjCross& other); + Data(const EtcObjCapsule& other); // Added + Data(const EtcObjCylinder& other); // Added }; EtcObjType type; color4u8 color; bool constant; Data data; - GLsizei count; // Added - size_t offset; // Added EtcObj(EtcObjType type); ~EtcObj(); }; + struct EtcObjData { + color4u8 color; + bool constant; + int32_t index; + int32_t count; + }; + typedef void(*UserArgsFunc)(render_data_context& rend_data_ctx, void* data, const cam_data& cam, mat4* mat); struct UserArgs { @@ -344,7 +359,7 @@ namespace mdl { struct ObjData { union Args { ObjSubMeshArgs sub_mesh; - EtcObj etc; + EtcObjData etc; UserArgs user; ObjTranslucentArgs translucent; @@ -361,7 +376,7 @@ namespace mdl { ObjData(); ~ObjData(); - void init_etc(DispManager* disp_manager, const mat4& mat, const mdl::EtcObj& etc); + void init_etc(DispManager* disp_manager, const mat4& mat, int32_t index, int32_t count, const EtcObj& etc); void init_sub_mesh(DispManager* disp_manager, const mat4& mat, float_t radius, const obj_sub_mesh* sub_mesh, const obj_mesh* mesh, const obj_material_data* material, const std::vector* textures, int32_t mat_count, const mat4* mats, GLuint vertex_buffer, size_t vertex_buffer_offset, @@ -389,6 +404,73 @@ namespace mdl { bool(*func)(const obj_bounding_sphere*, const mat4*); }; + struct etc_obj_draw_param_attrib_member { + uint32_t primitive : 4; + }; + + union etc_obj_draw_param_attrib { + etc_obj_draw_param_attrib_member m; + uint32_t w; + }; + + struct etc_obj_draw_param { + union { + GLint first; + struct { + GLuint start; + GLuint end; + }; + }; + GLsizei count; + GLintptr offset; + etc_obj_draw_param_attrib attrib; + }; + + struct etc_obj_vertex_data { + vec3 position; + vec3 normal; + + inline etc_obj_vertex_data(const vec3 position = vec3(0.0f), const vec3 normal = vec3(0.0f, 1.0f, 0.0f)) + : position(position), normal(normal) { + + } + }; + + struct EtcObjManager { + std::vector draw_param_buffer; + std::vector vertex_buffer; + std::vector index_buffer; + prj::vector_pair, EtcObj::Data> etc_obj_buffer; + + GLuint vao; + GL::ArrayBuffer vbo; + size_t vbo_vertex_count; + GL::ElementArrayBuffer ebo; + size_t ebo_index_count; + + EtcObjManager(); + ~EtcObjManager(); + + bool add_capsule(int32_t& index, int32_t& count, const EtcObjCapsule& capsule); // Added + bool add_cone(int32_t& index, int32_t& count, const EtcObjCone& cone); + bool add_cross(int32_t& index, int32_t& count, const EtcObjCross& cross); + bool add_cube(int32_t& index, int32_t& count, const EtcObjCube& cube); + bool add_cylinder(int32_t& index, int32_t& count, const EtcObjCylinder& cylinder); // Added + template + size_t add_data(T*& data, size_t num_vertex); + template + bool add_data(int32_t& index, T*& data, size_t num_vertex, GLenum primitive); + bool add_grid(int32_t& index, int32_t& count, const EtcObjGrid& grid); + bool add_line(int32_t& index, int32_t& count, const EtcObjLine& line); + bool add_obj(int32_t& index, int32_t& count, const EtcObj& etc); + bool add_plane(int32_t& index, int32_t& count, const EtcObjPlane& plane); + bool add_sphere(int32_t& index, int32_t& count, const EtcObjSphere& sphere); + void clear(); + void pre_draw(); + void post_draw(); + void update(); + }; + struct DispManager { struct vertex_array { GLuint vertex_buffer; @@ -408,22 +490,6 @@ namespace mdl { void reset_vertex_attrib(); }; - struct etc_vertex_array { - GL::ArrayBuffer vertex_buffer; - GL::ElementArrayBuffer index_buffer; - int32_t alive_time; - GLuint vertex_array; - EtcObj::Data data; - EtcObjType type; - bool indexed; - GLsizei count; - size_t offset; - GLsizei wire_count; - size_t wire_offset; - size_t max_vtx; - size_t max_idx; - }; - mdl::ObjFlags obj_flags; shadow_type_enum shadow_type; int32_t field_8; @@ -455,13 +521,11 @@ namespace mdl { int32_t material_list_count; material_list_struct material_list_array[MATERIAL_LIST_COUNT]; std::vector vertex_array_cache; - std::vector etc_vertex_array_cache; DispManager(); ~DispManager(); void add_vertex_array(ObjSubMeshArgs* args); - void add_vertex_array(EtcObj* etc, mat4& mat); void* alloc_data(int32_t size); ObjData* alloc_obj_data(ObjKind kind); mat4* alloc_mat4_array(int32_t count); @@ -514,7 +578,6 @@ namespace mdl { void entry_obj_etc_screen(const mat4& mat, const EtcObj& etc); void entry_obj_user(const mat4& mat, UserArgsFunc func, void* data, ObjType type); GLuint get_vertex_array(const ObjSubMeshArgs* args); - GLuint get_vertex_array(const EtcObj* etc); bool get_chara_color(); void get_material_list(int32_t& count, material_list_struct*& value); void get_morph(object_info& object, float_t& weight); diff --git a/src/CRE/mdl/draw_object.cpp b/src/CRE/mdl/draw_object.cpp index 5cbf7b3a..8ac54417 100644 --- a/src/CRE/mdl/draw_object.cpp +++ b/src/CRE/mdl/draw_object.cpp @@ -75,93 +75,49 @@ namespace mdl { stats.draw_triangle_count += count - 2; } - void draw_etc_obj(render_data_context& rend_data_ctx, const mdl::EtcObj* etc, const mat4* mat) { - switch (etc->type) { - case mdl::ETC_OBJ_TEAPOT: - case mdl::ETC_OBJ_GRID: - case mdl::ETC_OBJ_CUBE: - case mdl::ETC_OBJ_SPHERE: - case mdl::ETC_OBJ_PLANE: - case mdl::ETC_OBJ_CONE: - case mdl::ETC_OBJ_LINE: - case mdl::ETC_OBJ_CROSS: - case mdl::ETC_OBJ_CAPSULE: // Added - case mdl::ETC_OBJ_CYLINDER: // Added - break; - default: - return; + void draw_etc_obj(render_data_context& rend_data_ctx, const mdl::EtcObjData* etc, const mat4* mat) { + const vec4 normal_color = etc->color; + const vec4 const_color = 0.0f; + + const vec4* p_normal_color; + const vec4* p_const_color; + if (!etc->constant) { + p_normal_color = &normal_color; + p_const_color = &const_color; } - - if (!etc->count) - return; - - GLuint vao = rctx_ptr->disp_manager->get_vertex_array(etc); - if (!vao) - return; + else { + p_normal_color = &const_color; + p_const_color = &normal_color; + } + rend_data_ctx.set_batch_blend_color_offset_color(*p_normal_color, *p_const_color); rend_data_ctx.set_batch_worlds(*mat); - - const vec4 color = etc->color; - - if (etc->constant) - rend_data_ctx.set_batch_blend_color_offset_color(0.0f, color); - else - rend_data_ctx.set_batch_blend_color_offset_color(color, 0.0f); - - rend_data_ctx.state.bind_vertex_array(vao); rend_data_ctx.set_shader(SHADER_FT_SIMPLE); rend_data_ctx.set_render_data_state(); - switch (etc->type) { - case mdl::ETC_OBJ_TEAPOT: - rend_data_ctx.state.draw_elements(GL_TRIANGLES, etc->count, GL_UNSIGNED_INT, 0); - break; - case mdl::ETC_OBJ_GRID: - rend_data_ctx.state.set_line_width(0.2f); - rend_data_ctx.state.draw_arrays(GL_LINES, 0, etc->count); - rend_data_ctx.state.set_line_width(2.0f); - rend_data_ctx.state.draw_arrays(GL_LINES, (GLint)etc->count, 4); - rend_data_ctx.state.set_line_width(1.0f); - break; - case mdl::ETC_OBJ_CUBE: - if (etc->data.sphere.wire) - rend_data_ctx.state.draw_elements(GL_LINES, etc->count, GL_UNSIGNED_INT, (void*)etc->offset); - else - rend_data_ctx.state.draw_elements(GL_TRIANGLES, etc->count, GL_UNSIGNED_INT, (void*)etc->offset); - break; - case mdl::ETC_OBJ_SPHERE: - if (etc->data.sphere.wire) - rend_data_ctx.state.draw_elements(GL_LINES, etc->count, GL_UNSIGNED_INT, (void*)etc->offset); - else - rend_data_ctx.state.draw_elements(GL_TRIANGLES, etc->count, GL_UNSIGNED_INT, (void*)etc->offset); - break; - case mdl::ETC_OBJ_PLANE: - rend_data_ctx.state.draw_arrays(GL_TRIANGLE_STRIP, 0, etc->count); - break; - case mdl::ETC_OBJ_CONE: - if (etc->data.cone.wire) - rend_data_ctx.state.draw_elements(GL_LINES, etc->count, GL_UNSIGNED_INT, (void*)etc->offset); - else - rend_data_ctx.state.draw_elements(GL_TRIANGLES, etc->count, GL_UNSIGNED_INT, (void*)etc->offset); - break; - case mdl::ETC_OBJ_LINE: - rend_data_ctx.state.draw_arrays(GL_LINES, 0, etc->count); - break; - case mdl::ETC_OBJ_CROSS: - rend_data_ctx.state.draw_arrays(GL_LINES, 0, etc->count); - break; - case mdl::ETC_OBJ_CAPSULE: // Added - if (etc->data.capsule.wire) - rend_data_ctx.state.draw_elements(GL_LINES, etc->count, GL_UNSIGNED_INT, (void*)etc->offset); - else - rend_data_ctx.state.draw_elements(GL_TRIANGLES, etc->count, GL_UNSIGNED_INT, (void*)etc->offset); - break; - case mdl::ETC_OBJ_CYLINDER: // Added - if (etc->data.cylinder.wire) - rend_data_ctx.state.draw_elements(GL_LINES, etc->count, GL_UNSIGNED_INT, (void*)etc->offset); - else - rend_data_ctx.state.draw_elements(GL_TRIANGLES, etc->count, GL_UNSIGNED_INT, (void*)etc->offset); - break; + + rend_data_ctx.state.bind_vertex_array(0); + for (int32_t i = 0; i < 5; i++) { + rend_data_ctx.state.active_bind_texture_2d(i, rctx_ptr->empty_texture_2d->glid); + rend_data_ctx.state.bind_sampler(i, rctx_ptr->render_samplers[0]); } + rend_data_ctx.state.active_bind_texture_cube_map(5, rctx_ptr->empty_texture_cube_map->glid); + + if (etc->count) { + mdl::EtcObjManager* etc_obj_manager = rctx_ptr->etc_obj_manager; + int32_t index = etc->index; + for (int32_t i = etc->count; i; i--, index++) { + rend_data_ctx.state.bind_vertex_array(etc_obj_manager->vao); + mdl::etc_obj_draw_param& draw_param = etc_obj_manager->draw_param_buffer.data()[index]; + if (!draw_param.end) + rend_data_ctx.state.draw_arrays( + draw_param.attrib.m.primitive, draw_param.first, draw_param.count); + else + rend_data_ctx.state.draw_range_elements( + draw_param.attrib.m.primitive, draw_param.start, draw_param.end, + draw_param.count, GL_UNSIGNED_INT, (void*)draw_param.offset); + } + } + shader::unbind(rend_data_ctx.state); rend_data_ctx.reset_shader_flags(); diff --git a/src/CRE/mdl/draw_object.hpp b/src/CRE/mdl/draw_object.hpp index ec4970e1..4d1b8e10 100644 --- a/src/CRE/mdl/draw_object.hpp +++ b/src/CRE/mdl/draw_object.hpp @@ -16,7 +16,7 @@ namespace mdl { render_data_context& rend_data_ctx, obj_primitive_type primitive_type, uint32_t count, uint16_t start, uint16_t end, obj_index_format index_format, size_t indices); extern void draw_etc_obj( - render_data_context& rend_data_ctx, const mdl::EtcObj* etc, const mat4* mat); + render_data_context& rend_data_ctx, const mdl::EtcObjData* etc, const mat4* mat); extern void draw_sub_mesh(render_data_context& rend_data_ctx, const ObjSubMeshArgs* args, const mat4* mat, void(*func)(render_data_context& rend_data_ctx, const ObjSubMeshArgs* args, const cam_data& cam, const mat4* mat), const cam_data& cam); diff --git a/src/CRE/render_context.cpp b/src/CRE/render_context.cpp index 46e9060e..0717c8fe 100644 --- a/src/CRE/render_context.cpp +++ b/src/CRE/render_context.cpp @@ -983,6 +983,7 @@ sprite_width(), sprite_height(), screen_x_offset(), screen_y_offset(), screen_wi camera = new ::camera; draw_state = new ::draw_state; disp_manager = new mdl::DispManager; + etc_obj_manager = new mdl::EtcObjManager; render_manager = new rndr::RenderManager; sss_data = new ::sss_data; @@ -1243,6 +1244,11 @@ render_context::~render_context() { render_manager = 0; } + if (etc_obj_manager) { + delete etc_obj_manager; + etc_obj_manager = 0; + } + if (disp_manager) { delete disp_manager; disp_manager = 0; diff --git a/src/CRE/render_manager.cpp b/src/CRE/render_manager.cpp index 780c3d13..b887113e 100644 --- a/src/CRE/render_manager.cpp +++ b/src/CRE/render_manager.cpp @@ -304,6 +304,7 @@ namespace rndr { void RenderManager::render_all() { gl_state.get(); sprite_manager_pre_draw(); + rctx_ptr->etc_obj_manager->pre_draw(); { render_data_context rend_data_ctx(GL_REND_STATE_PRE_3D); @@ -347,6 +348,7 @@ namespace rndr { } rctx_ptr->disp_manager->check_vertex_arrays(); + rctx_ptr->etc_obj_manager->post_draw(); sprite_manager_post_draw(); render_data_context rend_data_ctx(GL_REND_STATE_POST_2D);