[2816] | 1 | // |
---|
| 2 | // Lol Engine |
---|
| 3 | // |
---|
| 4 | // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net> |
---|
| 5 | // (c) 2009-2013 Cédric Lecacheur <jordx@free.fr> |
---|
| 6 | // (c) 2009-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com> |
---|
| 7 | // This program is free software; you can redistribute it and/or |
---|
| 8 | // modify it under the terms of the Do What The Fuck You Want To |
---|
| 9 | // Public License, Version 2, as published by Sam Hocevar. See |
---|
| 10 | // http://www.wtfpl.net/ for more details. |
---|
| 11 | // |
---|
| 12 | |
---|
| 13 | // |
---|
| 14 | // The EasyMesh class |
---|
| 15 | // ------------------ |
---|
| 16 | // |
---|
| 17 | |
---|
| 18 | #if defined HAVE_CONFIG_H |
---|
| 19 | # include "config.h" |
---|
| 20 | #endif |
---|
| 21 | |
---|
| 22 | #include "core.h" |
---|
| 23 | #include "easymesh/easymesh-compiler.h" |
---|
| 24 | |
---|
| 25 | LOLFX_RESOURCE_DECLARE(shiny); |
---|
| 26 | LOLFX_RESOURCE_DECLARE(shinydebugwireframe); |
---|
| 27 | LOLFX_RESOURCE_DECLARE(shinydebuglighting); |
---|
| 28 | LOLFX_RESOURCE_DECLARE(shinydebugnormal); |
---|
| 29 | LOLFX_RESOURCE_DECLARE(shinydebugUV); |
---|
| 30 | LOLFX_RESOURCE_DECLARE(shiny_SK); |
---|
| 31 | |
---|
| 32 | namespace lol |
---|
| 33 | { |
---|
| 34 | |
---|
| 35 | |
---|
| 36 | //----------------------------------------------------------------------------- |
---|
| 37 | GpuShaderData::GpuShaderData() |
---|
| 38 | { |
---|
| 39 | m_render_mode = DebugRenderMode::Default; |
---|
| 40 | } |
---|
| 41 | |
---|
| 42 | //----------------------------------------------------------------------------- |
---|
| 43 | GpuShaderData::GpuShaderData(uint16_t vert_decl_flags, Shader* shader, DebugRenderMode render_mode) |
---|
| 44 | { |
---|
| 45 | m_render_mode = render_mode; |
---|
| 46 | m_shader = shader; |
---|
| 47 | m_vert_decl_flags = vert_decl_flags; |
---|
| 48 | } |
---|
| 49 | |
---|
| 50 | //----------------------------------------------------------------------------- |
---|
| 51 | GpuShaderData::~GpuShaderData() |
---|
| 52 | { |
---|
| 53 | m_shader_uniform.Empty(); |
---|
| 54 | m_shader_attrib.Empty(); |
---|
| 55 | } |
---|
| 56 | |
---|
| 57 | //----------------------------------------------------------------------------- |
---|
| 58 | void GpuShaderData::AddUniform(const lol::String &new_uniform) |
---|
| 59 | { |
---|
| 60 | m_shader_uniform.Push(new_uniform, m_shader->GetUniformLocation(new_uniform.C())); |
---|
| 61 | } |
---|
| 62 | |
---|
| 63 | //----------------------------------------------------------------------------- |
---|
| 64 | void GpuShaderData::AddAttribute(const lol::String &new_attribute, VertexUsage usage, int index) |
---|
| 65 | { |
---|
| 66 | m_shader_attrib.Push(new_attribute, m_shader->GetAttribLocation(new_attribute.C(), usage, index)); |
---|
| 67 | } |
---|
| 68 | |
---|
| 69 | //----------------------------------------------------------------------------- |
---|
| 70 | ShaderUniform const *GpuShaderData::GetUniform(const lol::String &uniform) |
---|
| 71 | { |
---|
| 72 | for (int i = 0; i < m_shader_uniform.Count(); ++i) |
---|
| 73 | if (m_shader_uniform[i].m1 == uniform) |
---|
| 74 | return &m_shader_uniform[i].m2; |
---|
| 75 | return nullptr; |
---|
| 76 | } |
---|
| 77 | |
---|
| 78 | //----------------------------------------------------------------------------- |
---|
| 79 | ShaderAttrib const *GpuShaderData::GetAttribute(const lol::String &attribute) |
---|
| 80 | { |
---|
| 81 | for (int i = 0; i < m_shader_attrib.Count(); ++i) |
---|
| 82 | if (m_shader_attrib[i].m1 == attribute) |
---|
| 83 | return &m_shader_attrib[i].m2; |
---|
| 84 | return nullptr; |
---|
| 85 | } |
---|
| 86 | |
---|
| 87 | //----------------------------------------------------------------------------- |
---|
| 88 | DefaultShaderData::DefaultShaderData(DebugRenderMode render_mode) |
---|
| 89 | { |
---|
| 90 | bool with_UV = false; |
---|
| 91 | m_render_mode = render_mode; |
---|
| 92 | m_vert_decl_flags = (1 << VertexUsage::Position) | |
---|
| 93 | (1 << VertexUsage::Normal) | |
---|
| 94 | (1 << VertexUsage::Color); |
---|
| 95 | |
---|
| 96 | if (render_mode == DebugRenderMode::Default) |
---|
| 97 | m_shader = Shader::Create(LOLFX_RESOURCE_NAME(shiny)); |
---|
| 98 | else if (render_mode == DebugRenderMode::Wireframe) |
---|
| 99 | m_shader = Shader::Create(LOLFX_RESOURCE_NAME(shinydebugwireframe)); |
---|
| 100 | else if (render_mode == DebugRenderMode::Lighting) |
---|
| 101 | m_shader = Shader::Create(LOLFX_RESOURCE_NAME(shinydebuglighting)); |
---|
| 102 | else if (render_mode == DebugRenderMode::Normal) |
---|
| 103 | m_shader = Shader::Create(LOLFX_RESOURCE_NAME(shinydebugnormal)); |
---|
| 104 | else if (render_mode == DebugRenderMode::UV) |
---|
| 105 | { |
---|
| 106 | m_shader = Shader::Create(LOLFX_RESOURCE_NAME(shinydebugUV)); |
---|
| 107 | m_vert_decl_flags |= (1 << VertexUsage::TexCoord); |
---|
| 108 | with_UV = true; |
---|
| 109 | } |
---|
| 110 | SetupDefaultData(with_UV); |
---|
| 111 | } |
---|
| 112 | |
---|
| 113 | //----------------------------------------------------------------------------- |
---|
| 114 | DefaultShaderData::DefaultShaderData(uint16_t vert_decl_flags, Shader* shader, bool with_UV) |
---|
| 115 | : GpuShaderData(vert_decl_flags, shader, DebugRenderMode::Default) |
---|
| 116 | { |
---|
| 117 | SetupDefaultData(with_UV); |
---|
| 118 | } |
---|
| 119 | |
---|
| 120 | //----------------------------------------------------------------------------- |
---|
| 121 | void DefaultShaderData::SetupDefaultData(bool with_UV) |
---|
| 122 | { |
---|
| 123 | AddUniform("in_ModelView"); |
---|
| 124 | AddUniform("in_Inv_ModelView"); |
---|
| 125 | AddUniform("in_View"); |
---|
| 126 | AddUniform("in_Inv_View"); |
---|
| 127 | AddUniform("in_Proj"); |
---|
| 128 | AddUniform("in_NormalMat"); |
---|
| 129 | AddUniform("in_Damage"); |
---|
| 130 | AddUniform("u_Lights"); |
---|
| 131 | } |
---|
| 132 | |
---|
| 133 | //----------------------------------------------------------------------------- |
---|
| 134 | void DefaultShaderData::SetupShaderDatas(mat4 const &model) |
---|
| 135 | { |
---|
| 136 | mat4 proj = g_scene->GetCamera()->GetProjection(); |
---|
| 137 | mat4 view = g_scene->GetCamera()->GetView(); |
---|
| 138 | mat4 modelview = view * model; |
---|
| 139 | mat3 normalmat = transpose(inverse(mat3(modelview))); |
---|
| 140 | |
---|
| 141 | /* FIXME: this should be hidden in the shader */ |
---|
| 142 | /* FIXME: the 4th component of the position can be used for other things */ |
---|
| 143 | /* FIXME: GetUniform("blabla") is costly */ |
---|
| 144 | Array<Light *> const lights = g_scene->GetLights(); |
---|
| 145 | Array<vec4> light_data; |
---|
| 146 | for (int i = 0; i < lights.Count(); ++i) |
---|
| 147 | light_data << lights[i]->GetPosition() << lights[i]->GetColor(); |
---|
| 148 | while (light_data.Count() < 8) |
---|
| 149 | light_data << vec4(0.f) << vec4(0.f); |
---|
| 150 | m_shader->SetUniform(*GetUniform("u_Lights"), light_data); |
---|
| 151 | |
---|
| 152 | m_shader->SetUniform(*GetUniform("in_ModelView"), modelview); |
---|
| 153 | m_shader->SetUniform(*GetUniform("in_Inv_ModelView"), inverse(modelview)); |
---|
| 154 | m_shader->SetUniform(*GetUniform("in_View"), view); |
---|
| 155 | m_shader->SetUniform(*GetUniform("in_Inv_View"), inverse(view)); |
---|
| 156 | m_shader->SetUniform(*GetUniform("in_Proj"), proj); |
---|
| 157 | m_shader->SetUniform(*GetUniform("in_NormalMat"), normalmat); |
---|
| 158 | m_shader->SetUniform(*GetUniform("in_Damage"), 0); |
---|
| 159 | } |
---|
| 160 | |
---|
| 161 | //----------------------------------------------------------------------------- |
---|
| 162 | GpuEasyMeshData::GpuEasyMeshData() |
---|
| 163 | { |
---|
| 164 | m_vertexcount = 0; |
---|
| 165 | m_indexcount = 0; |
---|
| 166 | m_ibo = nullptr; |
---|
| 167 | } |
---|
| 168 | |
---|
| 169 | //----------------------------------------------------------------------------- |
---|
| 170 | GpuEasyMeshData::~GpuEasyMeshData() |
---|
| 171 | { |
---|
| 172 | m_gpudatas.Empty(); |
---|
| 173 | m_vdatas.Empty(); |
---|
| 174 | if (m_ibo) |
---|
| 175 | delete(m_ibo); |
---|
| 176 | } |
---|
| 177 | |
---|
| 178 | #define BUILD_VFLAG(bool_value, flag_value, check_flag) \ |
---|
| 179 | bool bool_value = (check_flag & (1 << flag_value)) != 0; \ |
---|
| 180 | check_flag &= ~(1 << flag_value); |
---|
| 181 | #define BUILD_VFLAG_OR(bool_value, flag_value, check_flag) \ |
---|
| 182 | bool_value = (bool_value || (check_flag & (1 << flag_value)) != 0); \ |
---|
| 183 | check_flag &= ~(1 << flag_value); |
---|
| 184 | #define BUILD_VFLAG_COUNT(bool_value, flag_value, check_flag, count_value) \ |
---|
| 185 | BUILD_VFLAG(bool_value, flag_value, check_flag) \ |
---|
| 186 | count_value += (int)bool_value; |
---|
| 187 | |
---|
| 188 | //----------------------------------------------------------------------------- |
---|
| 189 | void GpuEasyMeshData::AddGpuData(GpuShaderData* gpudata, EasyMesh* src_mesh) |
---|
| 190 | { |
---|
| 191 | uint16_t vflags = gpudata->m_vert_decl_flags; |
---|
| 192 | |
---|
| 193 | BUILD_VFLAG(has_position, VertexUsage::Position, vflags); |
---|
| 194 | BUILD_VFLAG(has_normal, VertexUsage::Normal, vflags); |
---|
| 195 | BUILD_VFLAG(has_color, VertexUsage::Color, vflags); |
---|
| 196 | BUILD_VFLAG(has_texcoord, VertexUsage::TexCoord, vflags); |
---|
| 197 | BUILD_VFLAG_OR(has_texcoord, VertexUsage::TexCoordExt, vflags); |
---|
| 198 | ASSERT(!vflags, "Vertex Usage setup is not implemented for %s, feel free to do so.", |
---|
| 199 | VertexUsage::GetNameList(vflags).C()); |
---|
| 200 | |
---|
| 201 | if (has_position) gpudata->AddAttribute(gpudata->GetInVertexName(), VertexUsage::Position, 0); |
---|
| 202 | if (has_normal) gpudata->AddAttribute(gpudata->GetInNormalName(), VertexUsage::Normal, 0); |
---|
| 203 | if (has_color) gpudata->AddAttribute(gpudata->GetInColorName(), VertexUsage::Color, 0); |
---|
| 204 | if (has_texcoord) gpudata->AddAttribute(gpudata->GetInTexCoordName(), VertexUsage::TexCoord, 0); |
---|
| 205 | |
---|
| 206 | SetupVertexData(gpudata->m_vert_decl_flags, src_mesh); |
---|
| 207 | |
---|
| 208 | if (!m_ibo) |
---|
| 209 | { |
---|
| 210 | Array<uint16_t> indexlist; |
---|
| 211 | for (int i = 0; i < src_mesh->m_indices.Count(); i += 3) |
---|
| 212 | { |
---|
| 213 | indexlist << src_mesh->m_indices[i + 0]; |
---|
| 214 | indexlist << src_mesh->m_indices[i + 1]; |
---|
| 215 | indexlist << src_mesh->m_indices[i + 2]; |
---|
| 216 | } |
---|
| 217 | |
---|
| 218 | m_ibo = new IndexBuffer(indexlist.Bytes()); |
---|
| 219 | void *indices = m_ibo->Lock(0, 0); |
---|
| 220 | memcpy(indices, &indexlist[0], indexlist.Bytes()); |
---|
| 221 | m_ibo->Unlock(); |
---|
| 222 | |
---|
| 223 | m_indexcount = indexlist.Count(); |
---|
| 224 | } |
---|
| 225 | |
---|
| 226 | if (m_gpudatas.Count() != DebugRenderMode::Max) |
---|
| 227 | { |
---|
| 228 | m_gpudatas.Reserve(DebugRenderMode::Max); |
---|
| 229 | for (int i = 0; i < DebugRenderMode::Max; i++) |
---|
| 230 | m_gpudatas << nullptr; |
---|
| 231 | } |
---|
| 232 | m_gpudatas[gpudata->m_render_mode] = gpudata; |
---|
| 233 | } |
---|
| 234 | |
---|
| 235 | //----------------------------------------------------------------------------- |
---|
| 236 | void GpuEasyMeshData::SetupVertexData(uint16_t vflags, EasyMesh* src_mesh) |
---|
| 237 | { |
---|
| 238 | for (int i = 0; i < m_vdatas.Count(); ++i) |
---|
| 239 | if (m_vdatas[i].m1 == vflags) |
---|
| 240 | return; |
---|
| 241 | |
---|
| 242 | VertexDeclaration* new_vdecl = nullptr; |
---|
| 243 | VertexBuffer* new_vbo = nullptr; |
---|
| 244 | void *vbo_data = nullptr; |
---|
| 245 | int vbo_bytes = 0; |
---|
| 246 | |
---|
| 247 | #define COPY_VBO \ |
---|
| 248 | new_vbo = new VertexBuffer(vbo_bytes); \ |
---|
| 249 | void *mesh = new_vbo->Lock(0, 0); \ |
---|
| 250 | memcpy(mesh, vbo_data, vbo_bytes); \ |
---|
| 251 | new_vbo->Unlock(); |
---|
| 252 | |
---|
| 253 | //Keep a count of the flags |
---|
| 254 | uint16_t saveflags = vflags; |
---|
| 255 | int flagnb = 0; |
---|
| 256 | BUILD_VFLAG_COUNT(has_position, VertexUsage::Position, saveflags, flagnb); |
---|
| 257 | BUILD_VFLAG_COUNT(has_normal, VertexUsage::Normal, saveflags, flagnb); |
---|
| 258 | BUILD_VFLAG_COUNT(has_color, VertexUsage::Color, saveflags, flagnb); |
---|
| 259 | BUILD_VFLAG_COUNT(has_texcoord, VertexUsage::TexCoord, saveflags, flagnb); |
---|
| 260 | BUILD_VFLAG_COUNT(has_texcoordExt,VertexUsage::TexCoordExt, saveflags, flagnb); |
---|
| 261 | ASSERT(!saveflags, "Vertex Declaration setup is not implemented for %s, feel free to do so.", |
---|
| 262 | VertexUsage::GetNameList(vflags).C()); |
---|
| 263 | |
---|
| 264 | if (has_position && has_normal && has_color && has_texcoord && has_texcoordExt && flagnb == 5) |
---|
| 265 | { |
---|
| 266 | new_vdecl = new VertexDeclaration( |
---|
| 267 | VertexStream<vec3,vec3,u8vec4,vec4>( |
---|
| 268 | VertexUsage::Position, |
---|
| 269 | VertexUsage::Normal, |
---|
| 270 | VertexUsage::Color, |
---|
| 271 | VertexUsage::TexCoord)); |
---|
| 272 | |
---|
| 273 | Array<vec3, vec3, u8vec4, vec4> vertexlist; |
---|
| 274 | for (int i = 0; i < src_mesh->m_vert.Count(); i++) |
---|
| 275 | vertexlist.Push(src_mesh->m_vert[i].m_coord, |
---|
| 276 | src_mesh->m_vert[i].m_normal, |
---|
| 277 | (u8vec4)(src_mesh->m_vert[i].m_color * 255.f), |
---|
| 278 | src_mesh->m_vert[i].m_texcoord); |
---|
| 279 | |
---|
| 280 | vbo_data = &vertexlist[0]; |
---|
| 281 | vbo_bytes = vertexlist.Bytes(); |
---|
| 282 | m_vertexcount = vertexlist.Count(); |
---|
| 283 | |
---|
| 284 | COPY_VBO; |
---|
| 285 | } |
---|
| 286 | else if (has_position && has_texcoord && has_texcoordExt && flagnb == 3) |
---|
| 287 | { |
---|
| 288 | new_vdecl = new VertexDeclaration(VertexStream<vec3,vec4>(VertexUsage::Position, VertexUsage::TexCoord)); |
---|
| 289 | |
---|
| 290 | Array<vec3, vec4> vertexlist; |
---|
| 291 | for (int i = 0; i < src_mesh->m_vert.Count(); i++) |
---|
| 292 | vertexlist.Push(src_mesh->m_vert[i].m_coord, src_mesh->m_vert[i].m_texcoord); |
---|
| 293 | |
---|
| 294 | vbo_data = &vertexlist[0]; |
---|
| 295 | vbo_bytes = vertexlist.Bytes(); |
---|
| 296 | m_vertexcount = vertexlist.Count(); |
---|
| 297 | |
---|
| 298 | COPY_VBO; |
---|
| 299 | } |
---|
| 300 | else if (has_position && has_texcoord && flagnb == 2) |
---|
| 301 | { |
---|
| 302 | new_vdecl = new VertexDeclaration(VertexStream<vec3,vec2>(VertexUsage::Position, VertexUsage::TexCoord)); |
---|
| 303 | |
---|
| 304 | Array<vec3, vec2> vertexlist; |
---|
| 305 | for (int i = 0; i < src_mesh->m_vert.Count(); i++) |
---|
| 306 | vertexlist.Push(src_mesh->m_vert[i].m_coord, src_mesh->m_vert[i].m_texcoord.xy); |
---|
| 307 | |
---|
| 308 | vbo_data = &vertexlist[0]; |
---|
| 309 | vbo_bytes = vertexlist.Bytes(); |
---|
| 310 | m_vertexcount = vertexlist.Count(); |
---|
| 311 | |
---|
| 312 | COPY_VBO; |
---|
| 313 | } |
---|
| 314 | else if (has_position && has_normal && has_color && has_texcoord && flagnb == 4) |
---|
| 315 | { |
---|
| 316 | new_vdecl = new VertexDeclaration( |
---|
| 317 | VertexStream<vec3,vec3,u8vec4,vec2>( |
---|
| 318 | VertexUsage::Position, |
---|
| 319 | VertexUsage::Normal, |
---|
| 320 | VertexUsage::Color, |
---|
| 321 | VertexUsage::TexCoord)); |
---|
| 322 | |
---|
| 323 | Array<vec3, vec3, u8vec4, vec2> vertexlist; |
---|
| 324 | for (int i = 0; i < src_mesh->m_vert.Count(); i++) |
---|
| 325 | vertexlist.Push(src_mesh->m_vert[i].m_coord, |
---|
| 326 | src_mesh->m_vert[i].m_normal, |
---|
| 327 | (u8vec4)(src_mesh->m_vert[i].m_color * 255.f), |
---|
| 328 | src_mesh->m_vert[i].m_texcoord.xy); |
---|
| 329 | |
---|
| 330 | vbo_data = &vertexlist[0]; |
---|
| 331 | vbo_bytes = vertexlist.Bytes(); |
---|
| 332 | m_vertexcount = vertexlist.Count(); |
---|
| 333 | |
---|
| 334 | COPY_VBO; |
---|
| 335 | } |
---|
| 336 | else if (has_position && has_normal && has_color && flagnb == 3) |
---|
| 337 | { |
---|
| 338 | new_vdecl = new VertexDeclaration( |
---|
| 339 | VertexStream<vec3,vec3,u8vec4>( |
---|
| 340 | VertexUsage::Position, |
---|
| 341 | VertexUsage::Normal, |
---|
| 342 | VertexUsage::Color)); |
---|
| 343 | |
---|
| 344 | Array<vec3,vec3,u8vec4> vertexlist; |
---|
| 345 | for (int i = 0; i < src_mesh->m_vert.Count(); i++) |
---|
| 346 | vertexlist.Push(src_mesh->m_vert[i].m_coord, |
---|
| 347 | src_mesh->m_vert[i].m_normal, |
---|
| 348 | (u8vec4)(src_mesh->m_vert[i].m_color * 255.f)); |
---|
| 349 | |
---|
| 350 | vbo_data = &vertexlist[0]; |
---|
| 351 | vbo_bytes = vertexlist.Bytes(); |
---|
| 352 | m_vertexcount = vertexlist.Count(); |
---|
| 353 | |
---|
| 354 | COPY_VBO; |
---|
| 355 | } |
---|
[2879] | 356 | else if (has_position && has_color && has_texcoord && has_texcoordExt && flagnb == 4) |
---|
| 357 | { |
---|
| 358 | new_vdecl = new VertexDeclaration(VertexStream<vec3,vec4,vec4>(VertexUsage::Position, VertexUsage::Color, VertexUsage::TexCoord)); |
---|
[2816] | 359 | |
---|
[2879] | 360 | Array<vec3, vec4, vec4> vertexlist; |
---|
| 361 | for (int i = 0; i < src_mesh->m_vert.Count(); i++) |
---|
| 362 | vertexlist.Push(src_mesh->m_vert[i].m_coord, src_mesh->m_vert[i].m_color, src_mesh->m_vert[i].m_texcoord); |
---|
| 363 | |
---|
| 364 | vbo_data = &vertexlist[0]; |
---|
| 365 | vbo_bytes = vertexlist.Bytes(); |
---|
| 366 | m_vertexcount = vertexlist.Count(); |
---|
| 367 | |
---|
| 368 | COPY_VBO; |
---|
| 369 | } |
---|
| 370 | else |
---|
| 371 | ASSERT(!saveflags, "Vertex Declaration combination is not implemented for %s, feel free to do so.", |
---|
| 372 | VertexUsage::GetNameList(vflags).C()); |
---|
| 373 | |
---|
[2816] | 374 | m_vdatas.Push(vflags, new_vdecl, new_vbo); |
---|
| 375 | } |
---|
| 376 | |
---|
| 377 | //----------------------------------------------------------------------------- |
---|
| 378 | void GpuEasyMeshData::RenderMeshData(mat4 const &model) |
---|
| 379 | { |
---|
| 380 | DebugRenderMode d = Video::GetDebugRenderMode(); |
---|
| 381 | GpuShaderData& gpu_sd = *(m_gpudatas[d]); |
---|
| 382 | |
---|
| 383 | int vdecl_idx = 0; |
---|
| 384 | for (; vdecl_idx < m_vdatas.Count(); ++vdecl_idx) |
---|
| 385 | if (m_vdatas[vdecl_idx].m1 == gpu_sd.m_vert_decl_flags) |
---|
| 386 | break; |
---|
| 387 | |
---|
| 388 | if (vdecl_idx >= m_vdatas.Count()) |
---|
| 389 | return; |
---|
| 390 | |
---|
| 391 | uint16_t vflags = m_vdatas[vdecl_idx].m1; |
---|
| 392 | VertexDeclaration* vdecl = m_vdatas[vdecl_idx].m2; |
---|
| 393 | VertexBuffer* vbo = m_vdatas[vdecl_idx].m3; |
---|
| 394 | |
---|
| 395 | gpu_sd.m_shader->Bind(); |
---|
| 396 | gpu_sd.SetupShaderDatas(model); |
---|
| 397 | |
---|
| 398 | vdecl->Bind(); |
---|
| 399 | |
---|
| 400 | BUILD_VFLAG(has_position, VertexUsage::Position, vflags); |
---|
| 401 | BUILD_VFLAG(has_normal, VertexUsage::Normal, vflags); |
---|
| 402 | BUILD_VFLAG(has_color, VertexUsage::Color, vflags); |
---|
| 403 | BUILD_VFLAG(has_texcoord, VertexUsage::TexCoord, vflags); |
---|
| 404 | BUILD_VFLAG_OR(has_texcoord,VertexUsage::TexCoordExt, vflags); |
---|
| 405 | ASSERT(!vflags, "Vertex Stream setup is not implemented for %s, feel free to do so.", |
---|
| 406 | VertexUsage::GetNameList(vflags).C()); |
---|
| 407 | |
---|
| 408 | int idx = 0; |
---|
| 409 | ShaderAttrib Attribs[4] = { lol::ShaderAttrib(), lol::ShaderAttrib(), lol::ShaderAttrib(), lol::ShaderAttrib() }; |
---|
| 410 | |
---|
| 411 | if (has_position) Attribs[idx++] = *gpu_sd.GetAttribute(gpu_sd.GetInVertexName()); |
---|
| 412 | if (has_normal) Attribs[idx++] = *gpu_sd.GetAttribute(gpu_sd.GetInNormalName()); |
---|
| 413 | if (has_color) Attribs[idx++] = *gpu_sd.GetAttribute(gpu_sd.GetInColorName()); |
---|
| 414 | if (has_texcoord) Attribs[idx++] = *gpu_sd.GetAttribute(gpu_sd.GetInTexCoordName()); |
---|
| 415 | |
---|
| 416 | vdecl->SetStream(vbo, Attribs[0], Attribs[1], Attribs[2], Attribs[3]); |
---|
| 417 | |
---|
| 418 | m_ibo->Bind(); |
---|
| 419 | vdecl->DrawIndexedElements(MeshPrimitive::Triangles, 0, 0, m_vertexcount, 0, m_indexcount); |
---|
| 420 | m_ibo->Unbind(); |
---|
| 421 | vdecl->Unbind(); |
---|
| 422 | } |
---|
| 423 | |
---|
| 424 | //----------------------------------------------------------------------------- |
---|
| 425 | EasyMesh::EasyMesh() |
---|
| 426 | : m_build_data(nullptr) |
---|
| 427 | { |
---|
| 428 | m_cursors.Push(0, 0); |
---|
| 429 | } |
---|
| 430 | |
---|
| 431 | //----------------------------------------------------------------------------- |
---|
| 432 | bool EasyMesh::Compile(char const *command) |
---|
| 433 | { |
---|
| 434 | EasyMeshCompiler mc(*this); |
---|
| 435 | return mc.ParseString(command); |
---|
| 436 | } |
---|
| 437 | |
---|
| 438 | //----------------------------------------------------------------------------- |
---|
| 439 | void EasyMesh::OpenBrace() |
---|
| 440 | { |
---|
| 441 | m_cursors.Push(m_vert.Count(), m_indices.Count()); |
---|
| 442 | } |
---|
| 443 | |
---|
| 444 | //----------------------------------------------------------------------------- |
---|
| 445 | void EasyMesh::CloseBrace() |
---|
| 446 | { |
---|
| 447 | m_cursors.Pop(); |
---|
| 448 | } |
---|
| 449 | //----------------------------------------------------------------------------- |
---|
| 450 | void EasyMesh::MeshConvert(GpuShaderData* new_gpu_sdata) |
---|
| 451 | { |
---|
| 452 | delete(m_build_data); |
---|
| 453 | m_build_data = nullptr; |
---|
| 454 | |
---|
| 455 | if (new_gpu_sdata) |
---|
| 456 | { |
---|
| 457 | m_gpu_data.AddGpuData(new_gpu_sdata, this); |
---|
| 458 | for (int i = DebugRenderMode::Default + 1; i < DebugRenderMode::Max; i++) |
---|
| 459 | m_gpu_data.AddGpuData(new DefaultShaderData(DebugRenderMode(i)), this); |
---|
| 460 | } |
---|
| 461 | } |
---|
| 462 | |
---|
| 463 | //----------------------------------------------------------------------------- |
---|
| 464 | void EasyMesh::MeshConvert(Shader* provided_shader) |
---|
| 465 | { |
---|
| 466 | if (provided_shader) |
---|
| 467 | { |
---|
| 468 | GpuShaderData *new_gpu_sdata = new DefaultShaderData(((1 << VertexUsage::Position) | |
---|
| 469 | (1 << VertexUsage::Normal) | |
---|
| 470 | (1 << VertexUsage::Color)), |
---|
| 471 | provided_shader, |
---|
| 472 | false); |
---|
| 473 | m_gpu_data.AddGpuData(new_gpu_sdata, this); |
---|
| 474 | } |
---|
| 475 | else |
---|
| 476 | m_gpu_data.AddGpuData(new DefaultShaderData(DebugRenderMode::Default), this); |
---|
| 477 | for (int i = DebugRenderMode::Default + 1; i < DebugRenderMode::Max; i++) |
---|
| 478 | m_gpu_data.AddGpuData(new DefaultShaderData(DebugRenderMode(i)), this); |
---|
| 479 | } |
---|
| 480 | |
---|
| 481 | //----------------------------------------------------------------------------- |
---|
| 482 | void EasyMesh::Render(mat4 const &model) |
---|
| 483 | { |
---|
| 484 | m_gpu_data.RenderMeshData(model); |
---|
| 485 | } |
---|
| 486 | |
---|
| 487 | //------------------- |
---|
| 488 | // "Collisions" functions |
---|
| 489 | //------------------- |
---|
| 490 | #define VX_ALONE -2 |
---|
| 491 | #define VX_MASTER -1 |
---|
| 492 | |
---|
| 493 | //----------------------------------------------------------------------------- |
---|
| 494 | //helpers func to retrieve a vertex. |
---|
| 495 | int VertexDictionnary::FindVertexMaster(const int search_idx) |
---|
| 496 | { |
---|
| 497 | //Resolve current vertex idx in the dictionnary (if exist) |
---|
| 498 | for (int j = 0; j < vertex_list.Count(); j++) |
---|
| 499 | if (vertex_list[j].m1 == search_idx) |
---|
| 500 | return vertex_list[j].m3; |
---|
| 501 | return VDictType::DoesNotExist; |
---|
| 502 | } |
---|
| 503 | |
---|
| 504 | //----------------------------------------------------------------------------- |
---|
| 505 | //retrieve a list of matching vertices, doesn't include search_idx. |
---|
| 506 | bool VertexDictionnary::FindMatchingVertices(const int search_idx, Array<int> &matching_ids) |
---|
| 507 | { |
---|
| 508 | int cur_mast = FindVertexMaster(search_idx); |
---|
| 509 | |
---|
| 510 | if (cur_mast == VDictType::DoesNotExist || cur_mast == VDictType::Alone) |
---|
| 511 | return false; |
---|
| 512 | |
---|
| 513 | if (cur_mast == VDictType::Master) |
---|
| 514 | cur_mast = search_idx; |
---|
| 515 | else |
---|
| 516 | matching_ids << vertex_list[cur_mast].m1; |
---|
| 517 | |
---|
| 518 | for (int j = 0; j < vertex_list.Count(); j++) |
---|
| 519 | if (vertex_list[j].m3 == cur_mast && vertex_list[j].m1 != search_idx) |
---|
| 520 | matching_ids << vertex_list[j].m1; |
---|
| 521 | |
---|
| 522 | return (matching_ids.Count() > 0); |
---|
| 523 | } |
---|
| 524 | |
---|
| 525 | //----------------------------------------------------------------------------- |
---|
| 526 | //Will return connected vertices (through triangles), if returned vertex has matching ones, it only returns the master. |
---|
| 527 | bool VertexDictionnary::FindConnectedVertices(const int search_idx, const Array<uint16_t> &tri_list, const int tri0, Array<int> &connected_vert, Array<int> const *ignored_tri) |
---|
| 528 | { |
---|
| 529 | Array<int> connected_tri; |
---|
| 530 | FindConnectedTriangles(search_idx, tri_list, tri0, connected_tri, ignored_tri); |
---|
| 531 | |
---|
| 532 | for (int i = 0; i < connected_tri.Count(); i++) |
---|
| 533 | { |
---|
| 534 | for (int j = 0; j < 3; j++) |
---|
| 535 | { |
---|
| 536 | int v_indice = tri_list[connected_tri[i] + j]; |
---|
| 537 | if (v_indice != search_idx) |
---|
| 538 | { |
---|
| 539 | int found_master = FindVertexMaster(tri_list[connected_tri[i] + j]); |
---|
| 540 | if (found_master == VDictType::Alone || found_master == VDictType::Master) |
---|
| 541 | found_master = v_indice; |
---|
| 542 | if (found_master != search_idx) |
---|
| 543 | { |
---|
| 544 | bool already_exist = false; |
---|
| 545 | for (int k = 0; !already_exist && k < connected_vert.Count(); k++) |
---|
| 546 | if (connected_vert[k] == found_master) |
---|
| 547 | already_exist = true; |
---|
| 548 | if (!already_exist) |
---|
| 549 | connected_vert << found_master; |
---|
| 550 | } |
---|
| 551 | } |
---|
| 552 | } |
---|
| 553 | } |
---|
| 554 | return (connected_vert.Count() > 0); |
---|
| 555 | } |
---|
| 556 | //----------------------------------------------------------------------------- |
---|
| 557 | bool VertexDictionnary::FindConnectedTriangles(const int search_idx, const Array<uint16_t> &tri_list, const int tri0, Array<int> &connected_tri, Array<int> const *ignored_tri) |
---|
| 558 | { |
---|
| 559 | return FindConnectedTriangles(ivec3(search_idx, search_idx, search_idx), tri_list, tri0, connected_tri, ignored_tri); |
---|
| 560 | } |
---|
| 561 | //----------------------------------------------------------------------------- |
---|
| 562 | bool VertexDictionnary::FindConnectedTriangles(const ivec2 &search_idx, const Array<uint16_t> &tri_list, const int tri0, Array<int> &connected_tri, Array<int> const *ignored_tri) |
---|
| 563 | { |
---|
| 564 | return FindConnectedTriangles(ivec3(search_idx, search_idx.x), tri_list, tri0, connected_tri, ignored_tri); |
---|
| 565 | } |
---|
| 566 | //----------------------------------------------------------------------------- |
---|
| 567 | bool VertexDictionnary::FindConnectedTriangles(const ivec3 &search_idx, const Array<uint16_t> &tri_list, const int tri0, Array<int> &connected_tri, Array<int> const *ignored_tri) |
---|
| 568 | { |
---|
| 569 | int needed_validation = 0; |
---|
| 570 | Array<int> vert_list[3]; |
---|
| 571 | for (int i = 0; i < 3; i++) |
---|
| 572 | { |
---|
| 573 | //Small optim since above func will use this one |
---|
| 574 | if ((i == 1 && search_idx[0] == search_idx[1]) || |
---|
| 575 | (i == 2 && (search_idx[0] == search_idx[2] || search_idx[1] == search_idx[2]))) |
---|
| 576 | continue; |
---|
| 577 | else |
---|
| 578 | { |
---|
| 579 | //increment the validation info, hence empty list aren't taken into account. |
---|
| 580 | needed_validation++; |
---|
| 581 | vert_list[i] << search_idx[i]; |
---|
| 582 | FindMatchingVertices(search_idx[i], vert_list[i]); |
---|
| 583 | } |
---|
| 584 | } |
---|
| 585 | |
---|
| 586 | for (int i = tri0; i < tri_list.Count(); i += 3) |
---|
| 587 | { |
---|
| 588 | if (ignored_tri) |
---|
| 589 | { |
---|
| 590 | bool should_pass = false; |
---|
| 591 | for (int j = 0; !should_pass && j < ignored_tri->Count(); j++) |
---|
| 592 | if ((*ignored_tri)[j] == i) |
---|
| 593 | should_pass = true; |
---|
| 594 | if (should_pass) |
---|
| 595 | continue; |
---|
| 596 | } |
---|
| 597 | int found_validation = 0; |
---|
| 598 | for (int j = 0; j < 3; j++) |
---|
| 599 | { |
---|
| 600 | bool validated = false; |
---|
| 601 | for (int k = 0; !validated && k < vert_list[j].Count(); k++) |
---|
| 602 | for (int l = 0; !validated && l < 3; l++) |
---|
| 603 | if (vert_list[j][k] == tri_list[i + l]) |
---|
| 604 | validated = true; |
---|
| 605 | found_validation += (validated)?(1):(0); |
---|
| 606 | } |
---|
| 607 | //triangle is validated store it |
---|
| 608 | if (found_validation == needed_validation) |
---|
| 609 | connected_tri << i; |
---|
| 610 | } |
---|
| 611 | |
---|
| 612 | return (connected_tri.Count() > 0); |
---|
| 613 | } |
---|
| 614 | |
---|
| 615 | //----------------------------------------------------------------------------- |
---|
| 616 | //Will update the given list with all the vertices on the same spot. |
---|
| 617 | void VertexDictionnary::AddVertex(const int vert_id, const vec3 vert_coord) |
---|
| 618 | { |
---|
| 619 | for (int j = 0; j < vertex_list.Count(); j++) |
---|
| 620 | if (vertex_list[j].m1 == vert_id) |
---|
| 621 | return; |
---|
| 622 | |
---|
| 623 | //First, build the vertex Dictionnary |
---|
| 624 | int i = 0; |
---|
| 625 | for (; i < master_list.Count(); i++) |
---|
| 626 | { |
---|
| 627 | int cur_mast = master_list[i]; |
---|
| 628 | int cur_id = vertex_list[cur_mast].m1; |
---|
| 629 | vec3 cur_loc = vertex_list[cur_mast].m2; |
---|
| 630 | int &cur_type = vertex_list[cur_mast].m3; |
---|
| 631 | |
---|
| 632 | if (cur_id == vert_id) |
---|
| 633 | return; |
---|
| 634 | |
---|
| 635 | if (sqlength(cur_loc - vert_coord) < CSG_EPSILON) |
---|
| 636 | { |
---|
| 637 | if (cur_type == VDictType::Alone) |
---|
| 638 | cur_type = VDictType::Master; |
---|
| 639 | vertex_list.Push(vert_id, vert_coord, cur_mast); |
---|
| 640 | return; |
---|
| 641 | } |
---|
| 642 | } |
---|
| 643 | |
---|
| 644 | //We're here because we couldn't find any matching vertex |
---|
| 645 | master_list.Push(vertex_list.Count()); |
---|
| 646 | vertex_list.Push(vert_id, vert_coord, VDictType::Alone); |
---|
| 647 | } |
---|
| 648 | |
---|
| 649 | //----------------------------------------------------------------------------- |
---|
| 650 | void EasyMesh::MeshCsg(CSGUsage csg_operation) |
---|
| 651 | { |
---|
| 652 | //A vertex dictionnary for vertices on the same spot. |
---|
| 653 | Array< int, int > vertex_dict; |
---|
| 654 | //This list keeps track of the triangle that will need deletion at the end. |
---|
| 655 | Array< int > triangle_to_kill; |
---|
| 656 | //Listing for each triangle of the vectors intersecting it. <tri_Id, <Point0, Point1, tri_isec_Normal>> |
---|
| 657 | Array< int, Array< vec3, vec3, vec3 > > triangle_isec; |
---|
| 658 | //keep a track of the intersection point on the triangle. <pos, side_id> |
---|
| 659 | Array< vec3, int > triangle_vertex; |
---|
| 660 | for (int k = 0; k < 10; k++) |
---|
| 661 | triangle_vertex.Push(vec3(.0f), 0); |
---|
| 662 | |
---|
| 663 | //bsp infos |
---|
| 664 | CsgBsp mesh_bsp_0; |
---|
| 665 | CsgBsp mesh_bsp_1; |
---|
| 666 | |
---|
| 667 | if (m_cursors.Count() == 0) |
---|
| 668 | return; |
---|
| 669 | |
---|
| 670 | //BSP BUILD : We use the brace logic, csg should be used as : "[ exp .... [exp .... csg]]" |
---|
| 671 | int cursor_start = (m_cursors.Count() < 2)?(0):(m_cursors[(m_cursors.Count() - 2)].m2); |
---|
| 672 | for (int mesh_id = 0; mesh_id < 2; mesh_id++) |
---|
| 673 | { |
---|
| 674 | int start_point = (mesh_id == 0)?(cursor_start):(m_cursors.Last().m2); |
---|
| 675 | int end_point = (mesh_id == 0)?(m_cursors.Last().m2):(m_indices.Count()); |
---|
| 676 | CsgBsp &mesh_bsp = (mesh_id == 0)?(mesh_bsp_0):(mesh_bsp_1); |
---|
| 677 | for (int i = start_point; i < end_point; i += 3) |
---|
| 678 | mesh_bsp.AddTriangleToTree(i, m_vert[m_indices[i]].m_coord, |
---|
| 679 | m_vert[m_indices[i + 1]].m_coord, |
---|
| 680 | m_vert[m_indices[i + 2]].m_coord); |
---|
| 681 | } |
---|
| 682 | |
---|
| 683 | //BSP Useage : let's crunch all triangles on the correct BSP |
---|
| 684 | int indices_count = m_indices.Count(); |
---|
| 685 | for (int mesh_id = 0; mesh_id < 2; mesh_id++) |
---|
| 686 | { |
---|
| 687 | int start_point = (mesh_id == 0)?(cursor_start):(m_cursors.Last().m2); |
---|
| 688 | int end_point = (mesh_id == 0)?(m_cursors.Last().m2):(indices_count); |
---|
| 689 | CsgBsp &mesh_bsp = (mesh_id == 0)?(mesh_bsp_1):(mesh_bsp_0); |
---|
| 690 | Array< vec3, int, int, float > vert_list; |
---|
| 691 | Array< int, int, int, int > tri_list; |
---|
| 692 | vec3 n0(.0f); vec3 n1(.0f); |
---|
| 693 | vec4 c0(.0f); vec4 c1(.0f); |
---|
| 694 | |
---|
| 695 | //Reserve some memory |
---|
| 696 | vert_list.Reserve(3); |
---|
| 697 | tri_list.Reserve(3); |
---|
| 698 | |
---|
| 699 | for (int i = start_point; i < end_point; i += 3) |
---|
| 700 | { |
---|
| 701 | int Result = mesh_bsp.TestTriangleToTree(m_vert[m_indices[i]].m_coord, |
---|
| 702 | m_vert[m_indices[i + 1]].m_coord, |
---|
| 703 | m_vert[m_indices[i + 2]].m_coord, vert_list, tri_list); |
---|
| 704 | int tri_base_idx = m_indices.Count(); |
---|
| 705 | |
---|
| 706 | //one split has been done, we need to had the new vertices & the new triangles. |
---|
| 707 | if (Result == 1) |
---|
| 708 | { |
---|
| 709 | triangle_to_kill.Push(i); |
---|
| 710 | #if 1 |
---|
| 711 | int base_idx = m_vert.Count(); |
---|
| 712 | for (int k = 3; k < vert_list.Count(); k++) |
---|
| 713 | { |
---|
| 714 | int P0 = (vert_list[k].m2 < 3)?(m_indices[i + vert_list[k].m2]):(base_idx + vert_list[k].m2 - 3); |
---|
| 715 | int P1 = (vert_list[k].m3 < 3)?(m_indices[i + vert_list[k].m3]):(base_idx + vert_list[k].m3 - 3); |
---|
| 716 | |
---|
| 717 | AddVertex(vert_list[k].m1); |
---|
| 718 | |
---|
| 719 | //Normal : bad calculations there. |
---|
| 720 | n0 = m_vert[P0].m_normal; |
---|
| 721 | n1 = m_vert[P1].m_normal; |
---|
| 722 | SetCurVertNormal(normalize(n0 + (n1 - n0) * vert_list[k].m4)); |
---|
| 723 | |
---|
| 724 | #if 1 |
---|
| 725 | //Color |
---|
| 726 | c0 = m_vert[P0].m_color; |
---|
| 727 | c1 = m_vert[P1].m_color; |
---|
| 728 | vec4 res = c0 + ((c1 - c0) * vert_list[k].m4); |
---|
| 729 | SetCurVertColor(res); |
---|
| 730 | #else |
---|
| 731 | if (mesh_id == 0) |
---|
| 732 | SetCurVertColor(vec4(1.0f, .0f, .0f, 1.0f)); |
---|
| 733 | else |
---|
| 734 | SetCurVertColor(vec4(.0f, 1.0f, 1.0f, 1.0f)); |
---|
| 735 | #endif |
---|
| 736 | } |
---|
| 737 | for (int k = 0; k < tri_list.Count(); k++) |
---|
| 738 | { |
---|
| 739 | int P0 = (tri_list[k].m2 < 3)?(m_indices[i + tri_list[k].m2]):(base_idx + (tri_list[k].m2 - 3)); |
---|
| 740 | int P1 = (tri_list[k].m3 < 3)?(m_indices[i + tri_list[k].m3]):(base_idx + (tri_list[k].m3 - 3)); |
---|
| 741 | int P2 = (tri_list[k].m4 < 3)?(m_indices[i + tri_list[k].m4]):(base_idx + (tri_list[k].m4 - 3)); |
---|
| 742 | AppendTriangle(P0, P1, P2, 0); |
---|
| 743 | } |
---|
| 744 | #endif |
---|
| 745 | } |
---|
| 746 | #if 1 |
---|
| 747 | //Main case |
---|
| 748 | if (Result >= 0) |
---|
| 749 | { |
---|
| 750 | for (int k = 0; k < tri_list.Count(); k++) |
---|
| 751 | { |
---|
| 752 | int tri_idx = ((tri_list.Count() == 1)?(i):(tri_base_idx + k * 3)); |
---|
| 753 | |
---|
| 754 | //Triangle Kill Test |
---|
| 755 | if (//csgu : CSGUnion() -> m0_Outside + m1_Outside |
---|
| 756 | (csg_operation == CSGUsage::Union && tri_list[k].m1 == LEAF_BACK) || |
---|
| 757 | //csgs : CSGSubstract() -> m0_Outside + m1_Inside-inverted |
---|
| 758 | (csg_operation == CSGUsage::Substract && |
---|
| 759 | ((mesh_id == 0 && tri_list[k].m1 == LEAF_BACK) || |
---|
| 760 | (mesh_id == 1 && tri_list[k].m1 == LEAF_FRONT))) || |
---|
| 761 | //csgs : CSGSubstractLoss() -> m0_Outside |
---|
| 762 | (csg_operation == CSGUsage::SubstractLoss && |
---|
| 763 | ((mesh_id == 0 && tri_list[k].m1 == LEAF_BACK) || mesh_id == 1)) || |
---|
| 764 | //csga : CSGAnd() -> m0_Inside + m1_Inside |
---|
| 765 | (csg_operation == CSGUsage::And && tri_list[k].m1 == LEAF_FRONT)) |
---|
| 766 | { |
---|
| 767 | triangle_to_kill.Push(tri_idx); |
---|
| 768 | } |
---|
| 769 | |
---|
| 770 | //Triangle Invert Test |
---|
| 771 | if (//csgs : CSGSubstract() -> m0_Outside + m1_Inside-inverted |
---|
| 772 | (csg_operation == CSGUsage::Substract && mesh_id == 1 && tri_list[k].m1 == LEAF_BACK) || |
---|
| 773 | //csgx : CSGXor() -> m0_Outside/m0_Inside-inverted + m1_Outside/m1_Inside-inverted |
---|
| 774 | (csg_operation == CSGUsage::Xor && tri_list[k].m1 == LEAF_BACK)) |
---|
| 775 | { |
---|
| 776 | //a Xor means we will share vertices with the outside, so duplicate the vertices. |
---|
| 777 | //TODO : This operation disconnect all triangle, in some cases, not a good thing. |
---|
| 778 | if (csg_operation == CSGUsage::Xor) |
---|
| 779 | { |
---|
| 780 | for (int l = 0; l < 3; l++) |
---|
| 781 | { |
---|
| 782 | AddDuplicateVertex(m_indices[tri_idx + l]); |
---|
| 783 | m_indices[tri_idx + l] = m_vert.Count() - 1; |
---|
| 784 | } |
---|
| 785 | } |
---|
| 786 | m_indices[tri_idx + 1] += m_indices[tri_idx + 2]; |
---|
| 787 | m_indices[tri_idx + 2] = m_indices[tri_idx + 1] - m_indices[tri_idx + 2]; |
---|
| 788 | m_indices[tri_idx + 1] = m_indices[tri_idx + 1] - m_indices[tri_idx + 2]; |
---|
| 789 | ComputeNormals(tri_idx, 3); |
---|
| 790 | } |
---|
| 791 | } |
---|
| 792 | } |
---|
| 793 | #endif |
---|
| 794 | vert_list.Empty(); |
---|
| 795 | tri_list.Empty(); |
---|
| 796 | } |
---|
| 797 | } |
---|
| 798 | |
---|
| 799 | for (int i = 0; i < m_vert.Count(); i++) |
---|
| 800 | if (length(m_vert[i].m_normal) < 1.0f) |
---|
| 801 | i = i; |
---|
| 802 | |
---|
| 803 | int dir = 1; |
---|
| 804 | for (int i = 0; i >= 0 && i < triangle_to_kill.Count() - 1; i += dir) |
---|
| 805 | { |
---|
| 806 | if (triangle_to_kill[i] < triangle_to_kill[i + 1] && dir < 0) |
---|
| 807 | dir = 1; |
---|
| 808 | if (triangle_to_kill[i] == triangle_to_kill[i + 1]) |
---|
| 809 | { |
---|
| 810 | triangle_to_kill.Remove(i); |
---|
| 811 | dir = -1; |
---|
| 812 | } |
---|
| 813 | if (triangle_to_kill[i] > triangle_to_kill[i + 1]) |
---|
| 814 | { |
---|
| 815 | triangle_to_kill[i] += triangle_to_kill[i + 1]; |
---|
| 816 | triangle_to_kill[i + 1] = triangle_to_kill[i] - triangle_to_kill[i + 1]; |
---|
| 817 | triangle_to_kill[i] = triangle_to_kill[i] - triangle_to_kill[i + 1]; |
---|
| 818 | dir = -1; |
---|
| 819 | } |
---|
| 820 | if (i == 0 && dir == -1) |
---|
| 821 | dir = 1; |
---|
| 822 | } |
---|
| 823 | for (int i = triangle_to_kill.Count() - 1; i >= 0; i--) |
---|
| 824 | m_indices.Remove(triangle_to_kill[i], 3); |
---|
| 825 | |
---|
| 826 | m_cursors.Last().m1 = m_vert.Count(); |
---|
| 827 | m_cursors.Last().m2 = m_indices.Count(); |
---|
| 828 | |
---|
| 829 | //DONE for the splitting ! |
---|
| 830 | } |
---|
| 831 | |
---|
| 832 | //----------------------------------------------------------------------------- |
---|
| 833 | void EasyMesh::ToggleScaleWinding() |
---|
| 834 | { |
---|
| 835 | BD()->Toggle(MeshBuildOperation::Scale_Winding); |
---|
| 836 | } |
---|
| 837 | |
---|
| 838 | //----------------------------------------------------------------------------- |
---|
| 839 | void EasyMesh::SetCurColor(vec4 const &color) |
---|
| 840 | { |
---|
| 841 | BD()->Color() = color; |
---|
| 842 | } |
---|
| 843 | |
---|
| 844 | //----------------------------------------------------------------------------- |
---|
| 845 | void EasyMesh::SetCurColor2(vec4 const &color) |
---|
| 846 | { |
---|
| 847 | BD()->Color2() = color; |
---|
| 848 | } |
---|
| 849 | |
---|
| 850 | //----------------------------------------------------------------------------- |
---|
| 851 | void EasyMesh::AddVertex(vec3 const &coord) |
---|
| 852 | { |
---|
| 853 | m_vert.Push(VertexData(coord, vec3(0.f, 1.f, 0.f), BD()->Color())); |
---|
| 854 | } |
---|
| 855 | |
---|
| 856 | //----------------------------------------------------------------------------- |
---|
| 857 | void EasyMesh::AddDuplicateVertex(int i) |
---|
| 858 | { |
---|
| 859 | m_vert << m_vert[i]; |
---|
| 860 | } |
---|
| 861 | |
---|
| 862 | //----------------------------------------------------------------------------- |
---|
| 863 | void EasyMesh::AddLerpVertex(int i, int j, float alpha) |
---|
| 864 | { |
---|
| 865 | m_vert.Push(VertexData( |
---|
| 866 | lol::lerp(m_vert[i].m_coord, m_vert[j].m_coord, alpha), |
---|
| 867 | lol::lerp(m_vert[i].m_normal, m_vert[j].m_normal, alpha), |
---|
| 868 | lol::lerp(m_vert[i].m_color, m_vert[j].m_color, alpha), |
---|
| 869 | lol::lerp(m_vert[i].m_texcoord, m_vert[j].m_texcoord, alpha), |
---|
| 870 | ((alpha < .5f) ? (m_vert[i].m_bone_id) : (m_vert[j].m_bone_id)), /* FIXME ? */ |
---|
| 871 | lol::lerp(m_vert[i].m_bone_weight, m_vert[j].m_bone_weight, alpha))); |
---|
| 872 | } |
---|
| 873 | |
---|
| 874 | //----------------------------------------------------------------------------- |
---|
| 875 | void EasyMesh::AppendQuad(int i1, int i2, int i3, int i4, int base) |
---|
| 876 | { |
---|
| 877 | m_indices << base + i1; |
---|
| 878 | m_indices << base + i2; |
---|
| 879 | m_indices << base + i3; |
---|
| 880 | |
---|
| 881 | m_indices << base + i4; |
---|
| 882 | m_indices << base + i1; |
---|
| 883 | m_indices << base + i3; |
---|
| 884 | } |
---|
| 885 | |
---|
| 886 | //----------------------------------------------------------------------------- |
---|
| 887 | void EasyMesh::AppendQuadDuplicateVerts(int i1, int i2, int i3, int i4, int base) |
---|
| 888 | { |
---|
| 889 | m_indices << m_vert.Count(); AddDuplicateVertex(base + i1); |
---|
| 890 | m_indices << m_vert.Count(); AddDuplicateVertex(base + i2); |
---|
| 891 | m_indices << m_vert.Count(); AddDuplicateVertex(base + i3); |
---|
| 892 | |
---|
| 893 | m_indices << m_vert.Count(); AddDuplicateVertex(base + i4); |
---|
| 894 | m_indices << m_vert.Count(); AddDuplicateVertex(base + i1); |
---|
| 895 | m_indices << m_vert.Count(); AddDuplicateVertex(base + i3); |
---|
| 896 | } |
---|
| 897 | |
---|
| 898 | //----------------------------------------------------------------------------- |
---|
| 899 | void EasyMesh::AppendTriangle(int i1, int i2, int i3, int base) |
---|
| 900 | { |
---|
| 901 | m_indices << base + i1; |
---|
| 902 | m_indices << base + i2; |
---|
| 903 | m_indices << base + i3; |
---|
| 904 | } |
---|
| 905 | |
---|
| 906 | //----------------------------------------------------------------------------- |
---|
| 907 | void EasyMesh::AppendTriangleDuplicateVerts(int i1, int i2, int i3, int base) |
---|
| 908 | { |
---|
| 909 | m_indices << m_vert.Count(); AddDuplicateVertex(base + i1); |
---|
| 910 | m_indices << m_vert.Count(); AddDuplicateVertex(base + i2); |
---|
| 911 | m_indices << m_vert.Count(); AddDuplicateVertex(base + i3); |
---|
| 912 | } |
---|
| 913 | |
---|
| 914 | //----------------------------------------------------------------------------- |
---|
| 915 | void EasyMesh::ComputeNormals(int start, int vcount) |
---|
| 916 | { |
---|
| 917 | for (int i = 0; i < vcount; i += 3) |
---|
| 918 | { |
---|
| 919 | vec3 v0 = m_vert[m_indices[start + i + 2]].m_coord |
---|
| 920 | - m_vert[m_indices[start + i + 0]].m_coord; |
---|
| 921 | vec3 v1 = m_vert[m_indices[start + i + 1]].m_coord |
---|
| 922 | - m_vert[m_indices[start + i + 0]].m_coord; |
---|
| 923 | vec3 n = normalize(cross(v1, v0)); |
---|
| 924 | |
---|
| 925 | for (int j = 0; j < 3; j++) |
---|
| 926 | m_vert[m_indices[start + i + j]].m_normal = n; |
---|
| 927 | } |
---|
| 928 | } |
---|
| 929 | |
---|
| 930 | //----------------------------------------------------------------------------- |
---|
| 931 | void EasyMesh::ComputeTexCoord(float uv_scale, int uv_offset) |
---|
| 932 | { |
---|
| 933 | UNUSED(uv_scale, uv_offset); |
---|
| 934 | #if 0 |
---|
| 935 | VertexDictionnary vert_dict; |
---|
| 936 | Array<int> tri_list; |
---|
| 937 | |
---|
| 938 | tri_list.Reserve(m_indices.Count() - m_cursors.Last().m2); |
---|
| 939 | for (int i = m_cursors.Last().m2; i < m_indices.Count(); i++) |
---|
| 940 | { |
---|
| 941 | vert_dict.AddVertex(m_indices[i], m_vert[m_indices[i]].m_coord); |
---|
| 942 | tri_list << m_indices[i]; |
---|
| 943 | } |
---|
| 944 | |
---|
| 945 | //full triangle count |
---|
| 946 | Array<int> tri_done; |
---|
| 947 | Array<int> tri_check; |
---|
| 948 | int tri_count = (m_indices.Count() - m_cursors.Last().m2) / 3; |
---|
| 949 | |
---|
| 950 | tri_check << tri_list[0]; |
---|
| 951 | |
---|
| 952 | while (tri_check.Count()) |
---|
| 953 | { |
---|
| 954 | int cur_tri = tri_check[0]; |
---|
| 955 | int v[3] = { tri_list[cur_tri + uv_offset % 3], tri_list[cur_tri + (1 + uv_offset) % 3], tri_list[cur_tri + (2 + uv_offset) % 3] }; |
---|
| 956 | vec2 uv[3] = { m_vert[tri_list[cur_tri]].m_texcoord.xy, m_vert[tri_list[cur_tri + 1]].m_texcoord.xy, m_vert[tri_list[cur_tri + 2]].m_texcoord.xy }; |
---|
| 957 | for (int j = 0; j < 3; j++) |
---|
| 958 | { |
---|
| 959 | if (uv[j] != vec2(-1.0f) && uv[j] == uv[(j + 1) % 3]) |
---|
| 960 | { |
---|
| 961 | uv[0] = vec2(-1.0f); |
---|
| 962 | uv[1] = vec2(-1.0f); |
---|
| 963 | uv[2] = vec2(-1.0f); |
---|
| 964 | break; |
---|
| 965 | } |
---|
| 966 | } |
---|
| 967 | int uv_set = 0; |
---|
| 968 | for (int j = 0; j < 3; j++) |
---|
| 969 | uv_set += (uv[j].x < 0.f)?(0):(1); |
---|
| 970 | |
---|
| 971 | //this case shouldn't happen. |
---|
| 972 | if (uv_set == 1) |
---|
| 973 | { |
---|
| 974 | /* |
---|
| 975 | for (int j = 0; j < 3; j++) |
---|
| 976 | { |
---|
| 977 | if (uv[j] != vec2(-1.0f)) |
---|
| 978 | { |
---|
| 979 | uv[(j + 1) % 2] = uv[j] + vec2(.0f, uv_scale * length(m_vert[v[j]].m1 - m_vert[v[(j + 1) % 3]].m1)); |
---|
| 980 | uv_set = 2; |
---|
| 981 | break; |
---|
| 982 | } |
---|
| 983 | } |
---|
| 984 | */ |
---|
| 985 | } |
---|
| 986 | //No UV is set, let's do the arbitrary set and use the basic method. |
---|
| 987 | if (uv_set == 0) |
---|
| 988 | { |
---|
| 989 | float new_dot = FLT_MAX; |
---|
| 990 | int base_i = 0; |
---|
| 991 | for (int j = 0; j < 3; j++) |
---|
| 992 | { |
---|
| 993 | float tmp_dot = abs(dot(normalize(m_vert[v[(j + 1) % 3]].m_coord - m_vert[v[j]].m_coord), |
---|
| 994 | normalize(m_vert[v[(j + 2) % 3]].m_coord - m_vert[v[j]].m_coord))); |
---|
| 995 | if (tmp_dot < new_dot) |
---|
| 996 | { |
---|
| 997 | base_i = j; |
---|
| 998 | new_dot = tmp_dot; |
---|
| 999 | } |
---|
| 1000 | } |
---|
| 1001 | uv[base_i] = vec2(.0f); |
---|
| 1002 | uv[(base_i + 1) % 3] = vec2(.0f, uv_scale * length(m_vert[v[base_i]].m_coord - m_vert[v[(base_i + 1) % 3]].m_coord)); |
---|
| 1003 | uv_set = 2; |
---|
| 1004 | } |
---|
| 1005 | //2 points have been set, let's figure the third |
---|
| 1006 | if (uv_set == 2) |
---|
| 1007 | { |
---|
| 1008 | { |
---|
| 1009 | //invert values so the two set uv are in [0, 1] slots. |
---|
| 1010 | int new_v[3]; |
---|
| 1011 | vec2 new_uv[3]; |
---|
| 1012 | bool ignore_set = false; |
---|
| 1013 | if (uv[0].x >= 0.f && uv[1].x < 0.f) |
---|
| 1014 | { |
---|
| 1015 | new_v[0] = v[2]; new_v[1] = v[0]; new_v[2] = v[1]; |
---|
| 1016 | new_uv[0] = uv[2]; new_uv[1] = uv[0]; new_uv[2] = uv[1]; |
---|
| 1017 | } |
---|
| 1018 | else if (uv[0].x < 0.f && uv[1].x >= 0.f) |
---|
| 1019 | { |
---|
| 1020 | new_v[0] = v[1]; new_v[1] = v[2]; new_v[2] = v[0]; |
---|
| 1021 | new_uv[0] = uv[1]; new_uv[1] = uv[2]; new_uv[2] = uv[0]; |
---|
| 1022 | } |
---|
| 1023 | else |
---|
| 1024 | ignore_set = true; |
---|
| 1025 | if (!ignore_set) |
---|
| 1026 | { |
---|
| 1027 | v[0] = new_v[0]; v[1] = new_v[1]; v[2] = new_v[2]; |
---|
| 1028 | uv[0] = new_uv[0]; uv[1] = new_uv[1]; uv[2] = new_uv[2]; |
---|
| 1029 | } |
---|
| 1030 | } |
---|
| 1031 | |
---|
| 1032 | //Do this to be sure the normal is OK. |
---|
| 1033 | ComputeNormals(cur_tri, 3); |
---|
| 1034 | vec3 v01 = normalize(m_vert[v[1]].m_coord - m_vert[v[0]].m_coord); |
---|
| 1035 | vec3 v02 = m_vert[v[2]].m_coord - m_vert[v[0]].m_coord; |
---|
| 1036 | vec3 v_dir = normalize(cross(m_vert[m_indices[cur_tri]].m_normal, v01)); |
---|
| 1037 | vec2 texu_dir = uv[1] - uv[0]; |
---|
| 1038 | vec2 texv_dir = vec2(texu_dir.y, texu_dir.x); |
---|
| 1039 | //Final calculations |
---|
| 1040 | uv[2] = texu_dir * dot(v01, v02) + texv_dir * dot(v_dir, v02); |
---|
| 1041 | |
---|
| 1042 | //Set UV on ALL matching vertices! |
---|
| 1043 | Array<int> matching_vert; |
---|
| 1044 | for (int i = 0; i < 3; i++) |
---|
| 1045 | { |
---|
| 1046 | #if 1 |
---|
| 1047 | //This marks all same position UV to the same values |
---|
| 1048 | //Deactivation is a test. |
---|
| 1049 | matching_vert << v[i]; |
---|
| 1050 | vert_dict.FindMatchingVertices(v[i], matching_vert); |
---|
| 1051 | for (int j = 0; j < matching_vert.Count(); j++) |
---|
| 1052 | if (m_vert[matching_vert[j]].m_texcoord.xy == vec2(-1.0f)) |
---|
| 1053 | m_vert[matching_vert[j]].m_texcoord = vec4(abs(uv[i]), m_vert[matching_vert[j]].m_texcoord.zw); |
---|
| 1054 | #else |
---|
| 1055 | m_vert[v[i]].m_texcoord = abs(uv[i]); |
---|
| 1056 | #endif |
---|
| 1057 | } |
---|
| 1058 | |
---|
| 1059 | tri_done << cur_tri; |
---|
| 1060 | tri_check.Remove(0); |
---|
| 1061 | |
---|
| 1062 | //Get connected triangles and go from there. |
---|
| 1063 | for (int j = 0; j < 3; j++) |
---|
| 1064 | { |
---|
| 1065 | #if 1 |
---|
| 1066 | //This finds triangle that are connected to this triangle |
---|
| 1067 | vert_dict.FindConnectedTriangles(ivec2(v[j], v[(j + 1) % 3]), tri_list, tri_check, &tri_done); |
---|
| 1068 | #else |
---|
| 1069 | //This finds triangle that are connected to the vertices of this triangle |
---|
| 1070 | vert_dict.FindConnectedTriangles(v[j], tri_list, tri_check, &tri_done); |
---|
| 1071 | #endif |
---|
| 1072 | } |
---|
| 1073 | } |
---|
| 1074 | else if (uv_set == 3) |
---|
| 1075 | { |
---|
| 1076 | for (int j = 0; j < 3; j++) |
---|
| 1077 | { |
---|
| 1078 | m_vert[tri_list[cur_tri]].m_texcoord = vec4(vec2(-1.0f), m_vert[tri_list[cur_tri]].m_texcoord.zw); |
---|
| 1079 | m_vert[tri_list[cur_tri + 1]].m_texcoord = vec4(vec2(-1.0f), m_vert[tri_list[cur_tri + 1]].m_texcoord.zw); |
---|
| 1080 | m_vert[tri_list[cur_tri + 2]].m_texcoord = vec4(vec2(-1.0f), m_vert[tri_list[cur_tri + 2]].m_texcoord.zw); |
---|
| 1081 | } |
---|
| 1082 | |
---|
| 1083 | //uv[0] = vec2(-1.0f); |
---|
| 1084 | //uv[1] = vec2(-1.0f); |
---|
| 1085 | //uv[2] = vec2(-1.0f); |
---|
| 1086 | /* |
---|
| 1087 | bool tri_present = false; |
---|
| 1088 | for (int j = 0; j < tri_done.Count(); j++) |
---|
| 1089 | if (cur_tri == tri_done[j]) |
---|
| 1090 | tri_present = true; |
---|
| 1091 | if (!tri_present) |
---|
| 1092 | tri_done << cur_tri; |
---|
| 1093 | tri_check.Remove(0); |
---|
| 1094 | */ |
---|
| 1095 | } |
---|
| 1096 | |
---|
| 1097 | if (tri_check.Count() == 0 && tri_done.Count() != tri_count) |
---|
| 1098 | { |
---|
| 1099 | //look for unset triangle |
---|
| 1100 | for (int i = 0; !tri_check.Count() && i < tri_list.Count(); i += 3) |
---|
| 1101 | { |
---|
| 1102 | bool tri_present = false; |
---|
| 1103 | for (int j = 0; j < tri_done.Count(); j++) |
---|
| 1104 | if (i == tri_done[j]) |
---|
| 1105 | tri_present = true; |
---|
| 1106 | if (!tri_present) |
---|
| 1107 | tri_check << i; |
---|
| 1108 | } |
---|
| 1109 | } |
---|
| 1110 | } |
---|
| 1111 | #endif |
---|
| 1112 | } |
---|
| 1113 | |
---|
| 1114 | //----------------------------------------------------------------------------- |
---|
| 1115 | void EasyMesh::SetVertColor(vec4 const &color) |
---|
| 1116 | { |
---|
| 1117 | for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++) |
---|
| 1118 | m_vert[i].m_color = color; |
---|
| 1119 | } |
---|
| 1120 | |
---|
| 1121 | //----------------------------------------------------------------------------- |
---|
| 1122 | void EasyMesh::SetTexCoordData(vec2 const &new_offset, vec2 const &new_scale) |
---|
| 1123 | { |
---|
| 1124 | BD()->TexCoordOffset() = new_offset; |
---|
| 1125 | BD()->TexCoordScale() = new_scale; |
---|
| 1126 | } |
---|
| 1127 | |
---|
| 1128 | //----------------------------------------------------------------------------- |
---|
| 1129 | void EasyMesh::SetTexCoordData2(vec2 const &new_offset, vec2 const &new_scale) |
---|
| 1130 | { |
---|
| 1131 | BD()->TexCoordOffset2() = new_offset; |
---|
| 1132 | BD()->TexCoordScale2() = new_scale; |
---|
| 1133 | } |
---|
| 1134 | |
---|
| 1135 | //----------------------------------------------------------------------------- |
---|
| 1136 | void EasyMesh::SetCurVertNormal(vec3 const &normal) |
---|
| 1137 | { |
---|
| 1138 | m_vert[m_vert.Count() - 1].m_normal = normal; |
---|
| 1139 | } |
---|
| 1140 | |
---|
| 1141 | //----------------------------------------------------------------------------- |
---|
| 1142 | void EasyMesh::SetCurVertColor(vec4 const &color) |
---|
| 1143 | { |
---|
| 1144 | m_vert[m_vert.Count() - 1].m_color = color; |
---|
| 1145 | } |
---|
| 1146 | |
---|
| 1147 | //----------------------------------------------------------------------------- |
---|
| 1148 | void EasyMesh::SetCurVertTexCoord(vec2 const &texcoord) |
---|
| 1149 | { |
---|
| 1150 | m_vert[m_vert.Count() - 1].m_texcoord = vec4(texcoord, m_vert[m_vert.Count() - 1].m_texcoord.zw); |
---|
| 1151 | } |
---|
| 1152 | |
---|
| 1153 | //----------------------------------------------------------------------------- |
---|
| 1154 | void EasyMesh::SetCurVertTexCoord2(vec2 const &texcoord) |
---|
| 1155 | { |
---|
| 1156 | m_vert[m_vert.Count() - 1].m_texcoord = vec4(m_vert[m_vert.Count() - 1].m_texcoord.xy, texcoord); |
---|
| 1157 | } |
---|
| 1158 | |
---|
| 1159 | //----------------------------------------------------------------------------- |
---|
| 1160 | void EasyMesh::Translate(vec3 const &v) |
---|
| 1161 | { |
---|
| 1162 | for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++) |
---|
| 1163 | m_vert[i].m_coord += v; |
---|
| 1164 | } |
---|
| 1165 | |
---|
| 1166 | //----------------------------------------------------------------------------- |
---|
| 1167 | void EasyMesh::RotateX(float angle) { Rotate(angle, vec3(1, 0, 0)); } |
---|
| 1168 | void EasyMesh::RotateY(float angle) { Rotate(angle, vec3(0, 1, 0)); } |
---|
| 1169 | void EasyMesh::RotateZ(float angle) { Rotate(angle, vec3(0, 0, 1)); } |
---|
| 1170 | |
---|
| 1171 | //----------------------------------------------------------------------------- |
---|
| 1172 | void EasyMesh::Rotate(float angle, vec3 const &axis) |
---|
| 1173 | { |
---|
| 1174 | mat3 m = mat3::rotate(angle, axis); |
---|
| 1175 | for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++) |
---|
| 1176 | { |
---|
| 1177 | m_vert[i].m_coord = m * m_vert[i].m_coord; |
---|
| 1178 | m_vert[i].m_normal = m * m_vert[i].m_normal; |
---|
| 1179 | } |
---|
| 1180 | } |
---|
| 1181 | |
---|
| 1182 | //----------------------------------------------------------------------------- |
---|
| 1183 | void EasyMesh::RadialJitter(float r) |
---|
| 1184 | { |
---|
| 1185 | Array<int> Welded; |
---|
| 1186 | Welded.Push(-1); |
---|
| 1187 | for (int i = m_cursors.Last().m1 + 1; i < m_vert.Count(); i++) |
---|
| 1188 | { |
---|
| 1189 | int j, k; |
---|
| 1190 | for (j = m_cursors.Last().m1, k = 0; j < i; j++, k++) |
---|
| 1191 | { |
---|
| 1192 | if(Welded[k] < 0) |
---|
| 1193 | { |
---|
| 1194 | vec3 diff = m_vert[i].m_coord - m_vert[j].m_coord; |
---|
| 1195 | |
---|
| 1196 | if(diff.x > 0.1f || diff.x < -0.1f) |
---|
| 1197 | continue; |
---|
| 1198 | |
---|
| 1199 | if(diff.y > 0.1f || diff.y < -0.1f) |
---|
| 1200 | continue; |
---|
| 1201 | |
---|
| 1202 | if(diff.z > 0.1f || diff.z < -0.1f) |
---|
| 1203 | continue; |
---|
| 1204 | |
---|
| 1205 | break; |
---|
| 1206 | } |
---|
| 1207 | } |
---|
| 1208 | |
---|
| 1209 | if(j == i) |
---|
| 1210 | Welded.Push(-1); |
---|
| 1211 | else |
---|
| 1212 | Welded.Push(j); |
---|
| 1213 | } |
---|
| 1214 | |
---|
| 1215 | int i, j; |
---|
| 1216 | for (i = m_cursors.Last().m1, j = 0; i < m_vert.Count(); i++, j++) |
---|
| 1217 | { |
---|
| 1218 | if(Welded[j] == -1) |
---|
| 1219 | m_vert[i].m_coord *= 1.0f + rand(r); |
---|
| 1220 | else |
---|
| 1221 | m_vert[i].m_coord = m_vert[Welded[j]].m_coord; |
---|
| 1222 | } |
---|
| 1223 | |
---|
| 1224 | ComputeNormals(m_cursors.Last().m2, m_indices.Count() - m_cursors.Last().m2); |
---|
| 1225 | } |
---|
| 1226 | |
---|
| 1227 | //----------------------------------------------------------------------------- |
---|
| 1228 | void EasyMesh::TaperX(float ny, float nz, float xoff, int absolute) { DoMeshTransform(MeshTransform::Taper, Axis::X, Axis::X, ny, nz, xoff, absolute); } |
---|
| 1229 | void EasyMesh::TaperY(float nx, float nz, float yoff, int absolute) { DoMeshTransform(MeshTransform::Taper, Axis::Y, Axis::Y, nz, nx, yoff, absolute); } |
---|
| 1230 | void EasyMesh::TaperZ(float nx, float ny, float zoff, int absolute) { DoMeshTransform(MeshTransform::Taper, Axis::Z, Axis::Z, nx, ny, zoff, absolute); } |
---|
| 1231 | |
---|
| 1232 | //----------------------------------------------------------------------------- |
---|
| 1233 | void EasyMesh::TwistX(float t, float toff) { DoMeshTransform(MeshTransform::Twist, Axis::X, Axis::X, t, t, toff, 0); } |
---|
| 1234 | void EasyMesh::TwistY(float t, float toff) { DoMeshTransform(MeshTransform::Twist, Axis::Y, Axis::Y, t, t, toff, 0); } |
---|
| 1235 | void EasyMesh::TwistZ(float t, float toff) { DoMeshTransform(MeshTransform::Twist, Axis::Z, Axis::Z, t, t, toff, 0); } |
---|
| 1236 | |
---|
| 1237 | //----------------------------------------------------------------------------- |
---|
| 1238 | void EasyMesh::ShearX(float ny, float nz, float xoff, int absolute) { DoMeshTransform(MeshTransform::Shear, Axis::X, Axis::X, ny, nz, xoff, absolute); } |
---|
| 1239 | void EasyMesh::ShearY(float nx, float nz, float yoff, int absolute) { DoMeshTransform(MeshTransform::Shear, Axis::Y, Axis::Y, nz, nx, yoff, absolute); } |
---|
| 1240 | void EasyMesh::ShearZ(float nx, float ny, float zoff, int absolute) { DoMeshTransform(MeshTransform::Shear, Axis::Z, Axis::Z, nx, ny, zoff, absolute); } |
---|
| 1241 | |
---|
| 1242 | //----------------------------------------------------------------------------- |
---|
| 1243 | void EasyMesh::StretchX(float ny, float nz, float xoff) { DoMeshTransform(MeshTransform::Stretch, Axis::X, Axis::X, ny, nz, xoff, 0); } |
---|
| 1244 | void EasyMesh::StretchY(float nx, float nz, float yoff) { DoMeshTransform(MeshTransform::Stretch, Axis::Y, Axis::Y, nz, nx, yoff, 0); } |
---|
| 1245 | void EasyMesh::StretchZ(float nx, float ny, float zoff) { DoMeshTransform(MeshTransform::Stretch, Axis::Z, Axis::Z, nx, ny, zoff, 0); } |
---|
| 1246 | |
---|
| 1247 | //----------------------------------------------------------------------------- |
---|
| 1248 | void EasyMesh::BendXY(float t, float toff) { DoMeshTransform(MeshTransform::Bend, Axis::X, Axis::Y, t, t, toff, 0); } |
---|
| 1249 | void EasyMesh::BendXZ(float t, float toff) { DoMeshTransform(MeshTransform::Bend, Axis::X, Axis::Z, t, t, toff, 0); } |
---|
| 1250 | void EasyMesh::BendYX(float t, float toff) { DoMeshTransform(MeshTransform::Bend, Axis::Y, Axis::X, t, t, toff, 0); } |
---|
| 1251 | void EasyMesh::BendYZ(float t, float toff) { DoMeshTransform(MeshTransform::Bend, Axis::Y, Axis::Z, t, t, toff, 0); } |
---|
| 1252 | void EasyMesh::BendZX(float t, float toff) { DoMeshTransform(MeshTransform::Bend, Axis::Z, Axis::X, t, t, toff, 0); } |
---|
| 1253 | void EasyMesh::BendZY(float t, float toff) { DoMeshTransform(MeshTransform::Bend, Axis::Z, Axis::Y, t, t, toff, 0); } |
---|
| 1254 | |
---|
| 1255 | //----------------------------------------------------------------------------- |
---|
| 1256 | void EasyMesh::DoMeshTransform(MeshTransform ct, Axis axis0, Axis axis1, float n0, float n1, float noff, int absolute) |
---|
| 1257 | { |
---|
| 1258 | for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++) |
---|
| 1259 | { |
---|
| 1260 | switch (ct) |
---|
| 1261 | { |
---|
| 1262 | case MeshTransform::Taper: |
---|
| 1263 | { |
---|
| 1264 | float value = m_vert[i].m_coord[axis0]; |
---|
| 1265 | if (absolute) value = abs(value); |
---|
| 1266 | m_vert[i].m_coord[(axis0 + 1) % 3] *= max(0.f, 1.f + (n0 * value + noff)); |
---|
| 1267 | m_vert[i].m_coord[(axis0 + 2) % 3] *= max(0.f, 1.f + (n1 * value + noff)); |
---|
| 1268 | break; |
---|
| 1269 | } |
---|
| 1270 | case MeshTransform::Twist: |
---|
| 1271 | { |
---|
| 1272 | vec3 rotaxis = vec3(1.f); rotaxis[(axis0 + 1) % 3] = .0f; rotaxis[(axis0 + 2) % 3] = .0f; |
---|
| 1273 | m_vert[i].m_coord = mat3::rotate(m_vert[i].m_coord[axis0] * n0 + noff, rotaxis) * m_vert[i].m_coord; |
---|
| 1274 | break; |
---|
| 1275 | } |
---|
| 1276 | case MeshTransform::Shear: |
---|
| 1277 | { |
---|
| 1278 | float value = m_vert[i].m_coord[axis0]; |
---|
| 1279 | if (absolute) value = abs(value); |
---|
| 1280 | m_vert[i].m_coord[(axis0 + 1) % 3] += (n0 * value + noff); |
---|
| 1281 | m_vert[i].m_coord[(axis0 + 2) % 3] += (n1 * value + noff); |
---|
| 1282 | break; |
---|
| 1283 | } |
---|
| 1284 | case MeshTransform::Stretch: |
---|
| 1285 | { |
---|
| 1286 | //float value = abs(m_vert[i].m1[axis0]); |
---|
| 1287 | //m_vert[i].m1[(axis0 + 1) % 3] += (lol::pow(value, n0) + noff); |
---|
| 1288 | //m_vert[i].m1[(axis0 + 2) % 3] += (lol::pow(value, n1) + noff); |
---|
| 1289 | break; |
---|
| 1290 | } |
---|
| 1291 | case MeshTransform::Bend: |
---|
| 1292 | { |
---|
| 1293 | vec3 rotaxis = vec3(1.f); rotaxis[(axis1 + 1) % 3] = .0f; rotaxis[(axis1 + 2) % 3] = .0f; |
---|
| 1294 | m_vert[i].m_coord = mat3::rotate(m_vert[i].m_coord[axis0] * n0 + noff, rotaxis) * m_vert[i].m_coord; |
---|
| 1295 | break; |
---|
| 1296 | } |
---|
| 1297 | } |
---|
| 1298 | } |
---|
| 1299 | ComputeNormals(m_cursors.Last().m2, m_indices.Count() - m_cursors.Last().m2); |
---|
| 1300 | } |
---|
| 1301 | |
---|
| 1302 | //----------------------------------------------------------------------------- |
---|
| 1303 | void EasyMesh::Scale(vec3 const &s) |
---|
| 1304 | { |
---|
| 1305 | vec3 const invs = vec3(1) / s; |
---|
| 1306 | |
---|
| 1307 | for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++) |
---|
| 1308 | { |
---|
| 1309 | m_vert[i].m_coord *= s; |
---|
| 1310 | m_vert[i].m_normal = normalize(m_vert[i].m_normal * invs); |
---|
| 1311 | } |
---|
| 1312 | |
---|
| 1313 | /* Flip winding if the scaling involves mirroring */ |
---|
| 1314 | if (!BD()->IsEnabled(MeshBuildOperation::Scale_Winding) && s.x * s.y * s.z < 0) |
---|
| 1315 | { |
---|
| 1316 | for (int i = m_cursors.Last().m2; i < m_indices.Count(); i += 3) |
---|
| 1317 | { |
---|
| 1318 | uint16_t tmp = m_indices[i + 0]; |
---|
| 1319 | m_indices[i + 0] = m_indices[i + 1]; |
---|
| 1320 | m_indices[i + 1] = tmp; |
---|
| 1321 | } |
---|
| 1322 | } |
---|
| 1323 | } |
---|
| 1324 | |
---|
| 1325 | //----------------------------------------------------------------------------- |
---|
| 1326 | void EasyMesh::MirrorX() { DupAndScale(vec3(-1, 1, 1)); } |
---|
| 1327 | void EasyMesh::MirrorY() { DupAndScale(vec3(1, -1, 1)); } |
---|
| 1328 | void EasyMesh::MirrorZ() { DupAndScale(vec3(1, 1, -1)); } |
---|
| 1329 | |
---|
| 1330 | //----------------------------------------------------------------------------- |
---|
| 1331 | void EasyMesh::DupAndScale(vec3 const &s) |
---|
| 1332 | { |
---|
| 1333 | int vlen = m_vert.Count() - m_cursors.Last().m1; |
---|
| 1334 | int tlen = m_indices.Count() - m_cursors.Last().m2; |
---|
| 1335 | |
---|
| 1336 | for (int i = 0; i < vlen; i++) |
---|
| 1337 | AddDuplicateVertex(m_cursors.Last().m1++); |
---|
| 1338 | |
---|
| 1339 | for (int i = 0; i < tlen; i++) |
---|
| 1340 | m_indices << m_indices[m_cursors.Last().m2++] + vlen; |
---|
| 1341 | |
---|
| 1342 | Scale(s); |
---|
| 1343 | |
---|
| 1344 | m_cursors.Last().m1 -= vlen; |
---|
| 1345 | m_cursors.Last().m2 -= tlen; |
---|
| 1346 | } |
---|
| 1347 | |
---|
| 1348 | //----------------------------------------------------------------------------- |
---|
| 1349 | void EasyMesh::AppendCylinder(int nsides, float h, float d1, float d2, |
---|
| 1350 | int dualside, int smooth, int close) |
---|
| 1351 | { |
---|
| 1352 | //XXX : This operation is done to convert radius to diameter without changing all the code. |
---|
| 1353 | float r1 = d1 * .5f; |
---|
| 1354 | float r2 = d2 * .5f; |
---|
| 1355 | |
---|
| 1356 | //SAVE |
---|
| 1357 | vec4 Saved_Color = BD()->Color(); |
---|
| 1358 | vec4 Saved_Color2 = BD()->Color2(); |
---|
| 1359 | vec2 Save_texcoord_offset = BD()->TexCoordOffset(); |
---|
| 1360 | vec2 Save_texcoord_scale = BD()->TexCoordScale(); |
---|
| 1361 | |
---|
| 1362 | int vbase = m_vert.Count(); |
---|
| 1363 | |
---|
| 1364 | mat3 rotmat = mat3::rotate(360.0f / (float)nsides, 0.f, 1.f, 0.f); |
---|
| 1365 | vec3 p1(r1, -h * .5f, 0.f), p2(r2, h * .5f, 0.f), n; |
---|
| 1366 | vec2 uv1(.0f, .0f), uv2(.0f, 1.0f), uvadd(1.0f / (float)nsides, .0f); |
---|
| 1367 | if (close) |
---|
| 1368 | SetTexCoordData(vec2(.0f), vec2(1.0f, .5f)); |
---|
| 1369 | |
---|
| 1370 | /* Construct normal */ |
---|
| 1371 | if (r2 != .0f) |
---|
| 1372 | n = vec3(r2, h * .5f, 0.f); |
---|
| 1373 | else |
---|
| 1374 | n = vec3(r1, h * .5f, 0.f); |
---|
| 1375 | n.y = r1 * (r1 - r2) / h; |
---|
| 1376 | if (!smooth) |
---|
| 1377 | n = mat3::rotate(180.0f / nsides, 0.f, 1.f, 0.f) * n; |
---|
| 1378 | n = normalize(n); |
---|
| 1379 | |
---|
| 1380 | /* FIXME: normals should be flipped in two-sided mode, but that |
---|
| 1381 | * means duplicating the vertices again... */ |
---|
| 1382 | for (int i = 0; i < nsides; i++) |
---|
| 1383 | { |
---|
| 1384 | AddVertex(p1); SetCurVertNormal(n); SetCurVertTexCoord(uv1); SetCurVertTexCoord2(uv1); |
---|
| 1385 | AddVertex(p2); SetCurVertNormal(n); SetCurVertTexCoord(uv2); SetCurVertTexCoord2(uv2); |
---|
| 1386 | SetCurVertColor(BD()->Color2()); |
---|
| 1387 | |
---|
| 1388 | if (smooth) |
---|
| 1389 | { |
---|
| 1390 | int j = (i + 1) % nsides; |
---|
| 1391 | AppendQuad(j * 2, j * 2 + 1, i * 2 + 1, i * 2, vbase); |
---|
| 1392 | if (dualside) |
---|
| 1393 | AppendQuad(i * 2, i * 2 + 1, j * 2 + 1, j * 2, vbase); |
---|
| 1394 | } |
---|
| 1395 | |
---|
| 1396 | p1 = rotmat * p1; uv1 += uvadd; |
---|
| 1397 | p2 = rotmat * p2; uv2 += uvadd; |
---|
| 1398 | |
---|
| 1399 | if (!smooth) |
---|
| 1400 | { |
---|
| 1401 | AddVertex(p1); SetCurVertNormal(n); SetCurVertTexCoord(uv1); SetCurVertTexCoord2(uv1); |
---|
| 1402 | AddVertex(p2); SetCurVertNormal(n); SetCurVertTexCoord(uv2); SetCurVertTexCoord2(uv2); |
---|
| 1403 | SetCurVertColor(BD()->Color2()); |
---|
| 1404 | |
---|
| 1405 | AppendQuad(i * 4 + 2, i * 4 + 3, i * 4 + 1, i * 4, vbase); |
---|
| 1406 | if (dualside) |
---|
| 1407 | AppendQuad(i * 4, i * 4 + 1, i * 4 + 3, i * 4 + 2, vbase); |
---|
| 1408 | } |
---|
| 1409 | |
---|
| 1410 | n = rotmat * n; |
---|
| 1411 | } |
---|
| 1412 | |
---|
| 1413 | if (close) |
---|
| 1414 | { |
---|
| 1415 | //START |
---|
| 1416 | OpenBrace(); |
---|
| 1417 | //LOWER DISC |
---|
| 1418 | SetTexCoordData(vec2(.0f, .5f), vec2(.5f, .5f)); |
---|
| 1419 | SetCurColor(BD()->Color()); |
---|
| 1420 | AppendDisc(nsides, d1); |
---|
| 1421 | Translate(vec3(.0f, h, .0f)); |
---|
| 1422 | RotateX(180.0f); |
---|
| 1423 | //UPPER DISC |
---|
| 1424 | SetTexCoordData(vec2(.5f, .5f), vec2(.5f, .5f)); |
---|
| 1425 | SetCurColor(BD()->Color2()); |
---|
| 1426 | AppendDisc(nsides, d2); |
---|
| 1427 | Translate(vec3(.0f, h * .5f, .0f)); |
---|
| 1428 | CloseBrace(); |
---|
| 1429 | } |
---|
| 1430 | //RESTORE |
---|
| 1431 | SetCurColor(Saved_Color); |
---|
| 1432 | SetCurColor2(Saved_Color2); |
---|
| 1433 | SetTexCoordData(Save_texcoord_offset, Save_texcoord_scale); |
---|
| 1434 | } |
---|
| 1435 | |
---|
| 1436 | //----------------------------------------------------------------------------- |
---|
| 1437 | void EasyMesh::AppendSphere(int ndivisions, float d) |
---|
| 1438 | { |
---|
| 1439 | AppendCapsule(ndivisions, 0.f, d); |
---|
| 1440 | } |
---|
| 1441 | |
---|
| 1442 | //----------------------------------------------------------------------------- |
---|
| 1443 | void EasyMesh::AppendCapsule(int ndivisions, float h, float d) |
---|
| 1444 | { |
---|
| 1445 | //XXX : This operation is done to convert radius to diameter without changing all the code. |
---|
| 1446 | float r = d * .5f; |
---|
| 1447 | |
---|
| 1448 | int ibase = m_indices.Count(); |
---|
| 1449 | |
---|
| 1450 | Array<vec3> vertices; |
---|
| 1451 | float uv_h = 0; |
---|
| 1452 | float uv_r = 0; |
---|
| 1453 | |
---|
| 1454 | /* FIXME: we don't know how to handle even-divided capsules, so we |
---|
| 1455 | * force the count to be odd. */ |
---|
| 1456 | if (h) |
---|
| 1457 | { |
---|
| 1458 | ndivisions |= 1; |
---|
| 1459 | //calculate uv h&r percents |
---|
| 1460 | uv_h = (float)h / (float)(h + r * 2); |
---|
| 1461 | uv_r = (float)r / (float)(h + r * 2); |
---|
| 1462 | } |
---|
| 1463 | |
---|
| 1464 | /* Fill in the icosahedron vertices, rotating them so that there |
---|
| 1465 | * is a vertex at [0 1 0] and [0 -1 0] after normalisation. */ |
---|
| 1466 | float phi = 0.5f + 0.5f * sqrt(5.f); |
---|
| 1467 | mat3 mat = mat3::rotate(asin(1.f / sqrt(2.f + phi)) * (180.f / F_PI), |
---|
| 1468 | vec3(0.f, 0.f, 1.f)); |
---|
| 1469 | for (int i = 0; i < 4; i++) |
---|
| 1470 | { |
---|
| 1471 | float x = (i & 1) ? 0.5f : -0.5f; |
---|
| 1472 | float y = (i & 2) ? phi * 0.5f : phi * -0.5f; |
---|
| 1473 | vertices << mat * vec3(x, y, 0.f); |
---|
| 1474 | vertices << mat * vec3(0.f, x, y); |
---|
| 1475 | vertices << mat * vec3(y, 0.f, x); |
---|
| 1476 | } |
---|
| 1477 | |
---|
| 1478 | static int const trilist[] = |
---|
| 1479 | { |
---|
| 1480 | 0, 1, 2, 2, 4, 6, 3, 8, 1, 9, 4, 8, |
---|
| 1481 | 7, 0, 5, 7, 11, 3, 10, 5, 6, 10, 9, 11, |
---|
| 1482 | |
---|
| 1483 | 0, 3, 1, 7, 3, 0, 1, 4, 2, 8, 4, 1, |
---|
| 1484 | 2, 5, 0, 6, 5, 2, 6, 9, 10, 4, 9, 6, |
---|
| 1485 | 7, 10, 11, 5, 10, 7, 8, 11, 9, 3, 11, 8 |
---|
| 1486 | }; |
---|
| 1487 | |
---|
| 1488 | for (unsigned i = 0; i < sizeof(trilist) / sizeof(*trilist); i += 3) |
---|
| 1489 | { |
---|
| 1490 | vec3 const &a = vertices[trilist[i]]; |
---|
| 1491 | vec3 const &b = vertices[trilist[i + 1]]; |
---|
| 1492 | vec3 const &c = vertices[trilist[i + 2]]; |
---|
| 1493 | |
---|
| 1494 | vec3 const vb = 1.f / ndivisions * (b - a); |
---|
| 1495 | vec3 const vc = 1.f / ndivisions * (c - a); |
---|
| 1496 | |
---|
| 1497 | int line = ndivisions + 1; |
---|
| 1498 | |
---|
| 1499 | for (int v = 0, x = 0, y = 0; x < ndivisions + 1; v++) |
---|
| 1500 | { |
---|
| 1501 | vec3 p[] = { a + (float)x * vb + (float)y * vc, |
---|
| 1502 | p[0] + vb, |
---|
| 1503 | p[0] + vc, |
---|
| 1504 | p[0] + vb + vc }; |
---|
| 1505 | vec2 uv[4]; |
---|
| 1506 | |
---|
| 1507 | /* FIXME: when we normalise here, we get a volume that is slightly |
---|
| 1508 | * smaller than the sphere of radius 1, since we are not using |
---|
| 1509 | * the midradius. */ |
---|
| 1510 | for (int k = 0; k < 4; k++) |
---|
| 1511 | { |
---|
| 1512 | //keep normalized until the end of the UV calculations |
---|
| 1513 | p[k] = normalize(p[k]); |
---|
| 1514 | |
---|
| 1515 | uv[k].x = (lol::atan2(p[k].z, p[k].x) + F_PI) / (F_PI * 2.f); |
---|
| 1516 | if (abs(p[k].y) >= 1.0f) |
---|
| 1517 | uv[k].x = -1.f; |
---|
| 1518 | uv[k].y = lol::atan2(p[k].y, dot(p[k], normalize(p[k] * vec3(1.f,0.f,1.f)))) / F_PI + 0.5f; |
---|
| 1519 | if (h) |
---|
| 1520 | { |
---|
| 1521 | if (uv[k].y > .5f) |
---|
| 1522 | uv[k].y = uv_r + uv_h + (uv[k].y - .5f) * uv_r * 2.f; |
---|
| 1523 | else |
---|
| 1524 | uv[k].y *= uv_r * 2.f; |
---|
| 1525 | } |
---|
| 1526 | p[k] *= r; |
---|
| 1527 | } |
---|
| 1528 | |
---|
| 1529 | /* If this is a capsule, grow in the Y direction */ |
---|
| 1530 | if (h > 0.f) |
---|
| 1531 | { |
---|
| 1532 | for (int k = 0; k < 4; k++) |
---|
| 1533 | p[k].y += (p[k].y > 0.f) ? 0.5f * h : -0.5f * h; |
---|
| 1534 | } |
---|
| 1535 | |
---|
| 1536 | /* Add zero, one or two triangles */ |
---|
| 1537 | int id[] = { 0, 1, 2, |
---|
| 1538 | 1, 3 ,2 }; |
---|
| 1539 | int l = 6; |
---|
| 1540 | while ((l -= 3) >= 0) |
---|
| 1541 | { |
---|
| 1542 | if ((l == 0 && y < line - 1) || (l == 3 && y < line - 2)) |
---|
| 1543 | { |
---|
| 1544 | int k = -1; |
---|
| 1545 | while (++k < 3) |
---|
| 1546 | { |
---|
| 1547 | int rid[] = { id[k + l], id[(k + 1) % 3 + l] }; |
---|
| 1548 | if (uv[rid[0]].x >= .0f && |
---|
| 1549 | uv[rid[1]].x >= .0f && |
---|
| 1550 | abs(uv[rid[0]].x - uv[rid[1]].x) > .5f) |
---|
| 1551 | { |
---|
| 1552 | if (uv[rid[0]].x < uv[rid[1]].x) |
---|
| 1553 | uv[rid[0]].x += 1.0f; |
---|
| 1554 | else |
---|
| 1555 | uv[rid[1]].x += 1.0f; |
---|
| 1556 | } |
---|
| 1557 | } |
---|
| 1558 | k = -1; |
---|
| 1559 | while (++k < 3) |
---|
| 1560 | { |
---|
| 1561 | int rid[] = { id[k + l], id[(k + 1) % 3 + l], id[(k + 2) % 3 + l] }; |
---|
| 1562 | AddVertex(p[rid[0]]); |
---|
| 1563 | vec2 new_uv; |
---|
| 1564 | if (uv[rid[0]].x < .0f) |
---|
| 1565 | new_uv = vec2((uv[rid[1]].x + uv[rid[2]].x) * .5f, uv[rid[0]].y); |
---|
| 1566 | else |
---|
| 1567 | new_uv = uv[rid[0]]; |
---|
| 1568 | SetCurVertTexCoord(vec2(0.f, 1.f) - new_uv); |
---|
| 1569 | SetCurVertTexCoord2(vec2(0.f, 1.f) - new_uv); |
---|
| 1570 | } |
---|
| 1571 | AppendTriangle(0, 2, 1, m_vert.Count() - 3); |
---|
| 1572 | } |
---|
| 1573 | } |
---|
| 1574 | |
---|
| 1575 | y++; |
---|
| 1576 | if (y == line) |
---|
| 1577 | { |
---|
| 1578 | x++; |
---|
| 1579 | y = 0; |
---|
| 1580 | line--; |
---|
| 1581 | } |
---|
| 1582 | } |
---|
| 1583 | } |
---|
| 1584 | |
---|
| 1585 | ComputeNormals(ibase, m_indices.Count() - ibase); |
---|
| 1586 | } |
---|
| 1587 | |
---|
| 1588 | //----------------------------------------------------------------------------- |
---|
| 1589 | void EasyMesh::AppendTorus(int ndivisions, float d1, float d2) |
---|
| 1590 | { |
---|
| 1591 | //XXX : This operation is done to convert radius to diameter without changing all the code. |
---|
| 1592 | float r1 = d1 * .5f; |
---|
| 1593 | float r2 = d2 * .5f; |
---|
| 1594 | |
---|
| 1595 | int ibase = m_indices.Count(); |
---|
| 1596 | int nidiv = ndivisions; /* Cross-section */ |
---|
| 1597 | int njdiv = ndivisions; /* Full circumference */ |
---|
| 1598 | |
---|
| 1599 | for (int j = 0; j < njdiv; j++) |
---|
| 1600 | for (int i = 0; i < 2 * nidiv; i++) |
---|
| 1601 | { |
---|
| 1602 | for (int di = 0; di < 2; di++) |
---|
| 1603 | for (int dj = 0; dj < 2; dj++) |
---|
| 1604 | { |
---|
| 1605 | int i2 = (i + di) % nidiv; |
---|
| 1606 | int j2 = (j + dj) % njdiv; |
---|
| 1607 | |
---|
| 1608 | //Location on the donut |
---|
| 1609 | float x = 0.5f * (r2 - r1) * (float)lol::cos(2.f * F_PI * i2 / nidiv) + 0.5f * (r1 + r2); |
---|
| 1610 | float y = 0.5f * (r2 - r1) * (float)lol::sin(2.f * F_PI * i2 / nidiv); |
---|
| 1611 | float z = 0.0f; |
---|
| 1612 | |
---|
| 1613 | //Center circle |
---|
| 1614 | float ca = (float)lol::cos(2.f * F_PI * j2 / njdiv); |
---|
| 1615 | float sa = (float)lol::sin(2.f * F_PI * j2 / njdiv); |
---|
| 1616 | |
---|
| 1617 | //Actual location |
---|
| 1618 | float x2 = x * ca - z * sa; |
---|
| 1619 | float z2 = z * ca + x * sa; |
---|
| 1620 | |
---|
| 1621 | AddVertex(vec3(x2, y, z2)); |
---|
| 1622 | SetCurVertTexCoord(vec2((float)(i + di) / (float)nidiv, (float)(j + dj) / (float)nidiv)); |
---|
| 1623 | SetCurVertTexCoord2(vec2((float)(i + di) / (float)nidiv, (float)(j + dj) / (float)nidiv)); |
---|
| 1624 | } |
---|
| 1625 | |
---|
| 1626 | AppendTriangle(0, 2, 3, m_vert.Count() - 4); |
---|
| 1627 | AppendTriangle(0, 3, 1, m_vert.Count() - 4); |
---|
| 1628 | } |
---|
| 1629 | |
---|
| 1630 | ComputeNormals(ibase, m_indices.Count() - ibase); |
---|
| 1631 | } |
---|
| 1632 | |
---|
| 1633 | //----------------------------------------------------------------------------- |
---|
| 1634 | void EasyMesh::AppendBox(vec3 const &size, float chamf) |
---|
| 1635 | { |
---|
| 1636 | AppendBox(size, chamf, false); |
---|
| 1637 | } |
---|
| 1638 | |
---|
| 1639 | //----------------------------------------------------------------------------- |
---|
| 1640 | void EasyMesh::AppendSmoothChamfBox(vec3 const &size, float chamf) |
---|
| 1641 | { |
---|
| 1642 | AppendBox(size, chamf, true); |
---|
| 1643 | } |
---|
| 1644 | |
---|
| 1645 | //----------------------------------------------------------------------------- |
---|
| 1646 | void EasyMesh::AppendFlatChamfBox(vec3 const &size, float chamf) |
---|
| 1647 | { |
---|
| 1648 | AppendBox(size, chamf, false); |
---|
| 1649 | } |
---|
| 1650 | |
---|
| 1651 | //----------------------------------------------------------------------------- |
---|
| 1652 | void EasyMesh::AppendBox(vec3 const &size, float chamf, bool smooth) |
---|
| 1653 | { |
---|
| 1654 | if (chamf < 0.0f) |
---|
| 1655 | { |
---|
| 1656 | AppendBox(size + vec3(chamf * 2.0f), -chamf, smooth); |
---|
| 1657 | return; |
---|
| 1658 | } |
---|
| 1659 | |
---|
| 1660 | int vbase = m_vert.Count(); |
---|
| 1661 | int ibase = m_indices.Count(); |
---|
| 1662 | |
---|
| 1663 | vec3 d = size * 0.5f; |
---|
| 1664 | |
---|
| 1665 | MeshType mt = MeshType::Box; |
---|
| 1666 | TexCoordPos bl = TexCoordPos::BL; |
---|
| 1667 | TexCoordPos br = TexCoordPos::BR; |
---|
| 1668 | TexCoordPos tl = TexCoordPos::TL; |
---|
| 1669 | TexCoordPos tr = TexCoordPos::TR; |
---|
| 1670 | |
---|
| 1671 | //-- |
---|
| 1672 | //Side vertices |
---|
| 1673 | //-- |
---|
| 1674 | MeshFaceType mft = MeshFaceType::BoxFront; |
---|
| 1675 | AddVertex(vec3(-d.x, -d.y, -d.z - chamf)); |
---|
| 1676 | SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft)); |
---|
| 1677 | SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft)); |
---|
| 1678 | //-- |
---|
| 1679 | AddVertex(vec3(-d.x, +d.y, -d.z - chamf)); |
---|
| 1680 | SetCurVertTexCoord(BD()->TexCoord(mt, br, mft)); |
---|
| 1681 | SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft)); |
---|
| 1682 | //-- |
---|
| 1683 | AddVertex(vec3(+d.x, +d.y, -d.z - chamf)); |
---|
| 1684 | SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft)); |
---|
| 1685 | SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft)); |
---|
| 1686 | //-- |
---|
| 1687 | AddVertex(vec3(+d.x, -d.y, -d.z - chamf)); |
---|
| 1688 | SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft)); |
---|
| 1689 | SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft)); |
---|
| 1690 | |
---|
| 1691 | //-- |
---|
| 1692 | mft = MeshFaceType::BoxLeft; |
---|
| 1693 | AddVertex(vec3(-d.x - chamf, -d.y, +d.z)); |
---|
| 1694 | SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft)); |
---|
| 1695 | SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft)); |
---|
| 1696 | //-- |
---|
| 1697 | AddVertex(vec3(-d.x - chamf, +d.y, +d.z)); |
---|
| 1698 | SetCurVertTexCoord(BD()->TexCoord(mt, br, mft)); |
---|
| 1699 | SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft)); |
---|
| 1700 | //-- |
---|
| 1701 | AddVertex(vec3(-d.x - chamf, +d.y, -d.z)); |
---|
| 1702 | SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft)); |
---|
| 1703 | SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft)); |
---|
| 1704 | //-- |
---|
| 1705 | AddVertex(vec3(-d.x - chamf, -d.y, -d.z)); |
---|
| 1706 | SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft)); |
---|
| 1707 | SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft)); |
---|
| 1708 | |
---|
| 1709 | //-- |
---|
| 1710 | mft = MeshFaceType::BoxBack; |
---|
| 1711 | AddVertex(vec3(+d.x, -d.y, +d.z + chamf)); |
---|
| 1712 | SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft)); |
---|
| 1713 | SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft)); |
---|
| 1714 | //-- |
---|
| 1715 | AddVertex(vec3(+d.x, +d.y, +d.z + chamf)); |
---|
| 1716 | SetCurVertTexCoord(BD()->TexCoord(mt, br, mft)); |
---|
| 1717 | SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft)); |
---|
| 1718 | //-- |
---|
| 1719 | AddVertex(vec3(-d.x, +d.y, +d.z + chamf)); |
---|
| 1720 | SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft)); |
---|
| 1721 | SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft)); |
---|
| 1722 | //-- |
---|
| 1723 | AddVertex(vec3(-d.x, -d.y, +d.z + chamf)); |
---|
| 1724 | SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft)); |
---|
| 1725 | SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft)); |
---|
| 1726 | |
---|
| 1727 | //-- |
---|
| 1728 | mft = MeshFaceType::BoxRight; |
---|
| 1729 | AddVertex(vec3(+d.x + chamf, -d.y, -d.z)); |
---|
| 1730 | SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft)); |
---|
| 1731 | SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft)); |
---|
| 1732 | //-- |
---|
| 1733 | AddVertex(vec3(+d.x + chamf, +d.y, -d.z)); |
---|
| 1734 | SetCurVertTexCoord(BD()->TexCoord(mt, br, mft)); |
---|
| 1735 | SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft)); |
---|
| 1736 | //-- |
---|
| 1737 | AddVertex(vec3(+d.x + chamf, +d.y, +d.z)); |
---|
| 1738 | SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft)); |
---|
| 1739 | SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft)); |
---|
| 1740 | //-- |
---|
| 1741 | AddVertex(vec3(+d.x + chamf, -d.y, +d.z)); |
---|
| 1742 | SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft)); |
---|
| 1743 | SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft)); |
---|
| 1744 | |
---|
| 1745 | //-- |
---|
| 1746 | //Bottom vertices |
---|
| 1747 | //-- |
---|
| 1748 | mft = MeshFaceType::BoxBottom; |
---|
| 1749 | AddVertex(vec3(-d.x, -d.y - chamf, +d.z)); |
---|
| 1750 | SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft)); |
---|
| 1751 | SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft)); |
---|
| 1752 | //-- |
---|
| 1753 | AddVertex(vec3(-d.x, -d.y - chamf, -d.z)); |
---|
| 1754 | SetCurVertTexCoord(BD()->TexCoord(mt, br, mft)); |
---|
| 1755 | SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft)); |
---|
| 1756 | //-- |
---|
| 1757 | AddVertex(vec3(+d.x, -d.y - chamf, -d.z)); |
---|
| 1758 | SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft)); |
---|
| 1759 | SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft)); |
---|
| 1760 | //-- |
---|
| 1761 | AddVertex(vec3(+d.x, -d.y - chamf, +d.z)); |
---|
| 1762 | SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft)); |
---|
| 1763 | SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft)); |
---|
| 1764 | |
---|
| 1765 | //-- |
---|
| 1766 | //Top vertices |
---|
| 1767 | //-- |
---|
| 1768 | mft = MeshFaceType::BoxTop; |
---|
| 1769 | AddVertex(vec3(-d.x, +d.y + chamf, -d.z)); |
---|
| 1770 | SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft)); |
---|
| 1771 | SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft)); |
---|
| 1772 | //-- |
---|
| 1773 | AddVertex(vec3(-d.x, +d.y + chamf, +d.z)); |
---|
| 1774 | SetCurVertTexCoord(BD()->TexCoord(mt, br, mft)); |
---|
| 1775 | SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft)); |
---|
| 1776 | //-- |
---|
| 1777 | AddVertex(vec3(+d.x, +d.y + chamf, +d.z)); |
---|
| 1778 | SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft)); |
---|
| 1779 | SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft)); |
---|
| 1780 | //-- |
---|
| 1781 | AddVertex(vec3(+d.x, +d.y + chamf, -d.z)); |
---|
| 1782 | SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft)); |
---|
| 1783 | SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft)); |
---|
| 1784 | |
---|
| 1785 | /* The 6 quads on each side of the box */ |
---|
| 1786 | for (int i = 0; i < 24; i += 4) |
---|
| 1787 | AppendQuad(i, i + 1, i + 2, i + 3, vbase); |
---|
| 1788 | |
---|
| 1789 | ComputeNormals(ibase, m_indices.Count() - ibase); |
---|
| 1790 | ibase = m_indices.Count(); |
---|
| 1791 | |
---|
| 1792 | /* The 8 quads at each edge of the box */ |
---|
| 1793 | if (chamf) |
---|
| 1794 | { |
---|
| 1795 | static int const quadlist[48] = |
---|
| 1796 | { |
---|
| 1797 | 0, 3, 18, 17, 4, 7, 17, 16, 8, 11, 16, 19, 12, 15, 19, 18, |
---|
| 1798 | 2, 1, 20, 23, 6, 5, 21, 20, 10, 9, 22, 21, 14, 13, 23, 22, |
---|
| 1799 | 1, 0, 7, 6, 5, 4, 11, 10, 9, 8, 15, 14, 13, 12, 3, 2, |
---|
| 1800 | }; |
---|
| 1801 | |
---|
| 1802 | for (int i = 0; i < 48; i += 4) |
---|
| 1803 | { |
---|
| 1804 | if (smooth) |
---|
| 1805 | AppendQuad(quadlist[i], quadlist[i + 1], |
---|
| 1806 | quadlist[i + 2], quadlist[i + 3], vbase); |
---|
| 1807 | else |
---|
| 1808 | AppendQuadDuplicateVerts(quadlist[i], quadlist[i + 1], |
---|
| 1809 | quadlist[i + 2], quadlist[i + 3], vbase); |
---|
| 1810 | } |
---|
| 1811 | } |
---|
| 1812 | |
---|
| 1813 | /* The 8 triangles at each corner of the box */ |
---|
| 1814 | if (chamf) |
---|
| 1815 | { |
---|
| 1816 | static int const trilist[24] = |
---|
| 1817 | { |
---|
| 1818 | 3, 12, 18, 15, 8, 19, 11, 4, 16, 7, 0, 17, |
---|
| 1819 | 2, 23, 13, 14, 22, 9, 10, 21, 5, 6, 20, 1, |
---|
| 1820 | }; |
---|
| 1821 | |
---|
| 1822 | for (int i = 0; i < 24; i += 3) |
---|
| 1823 | { |
---|
| 1824 | if (smooth) |
---|
| 1825 | AppendTriangle(trilist[i], trilist[i + 1], |
---|
| 1826 | trilist[i + 2], vbase); |
---|
| 1827 | else |
---|
| 1828 | AppendTriangleDuplicateVerts(trilist[i], trilist[i + 1], |
---|
| 1829 | trilist[i + 2], vbase); |
---|
| 1830 | } |
---|
| 1831 | } |
---|
| 1832 | |
---|
| 1833 | if (!smooth) |
---|
| 1834 | ComputeNormals(ibase, m_indices.Count() - ibase); |
---|
| 1835 | } |
---|
| 1836 | |
---|
| 1837 | //----------------------------------------------------------------------------- |
---|
| 1838 | void EasyMesh::AppendStar(int nbranches, float d1, float d2, |
---|
| 1839 | int fade, int fade2) |
---|
| 1840 | { |
---|
| 1841 | //XXX : This operation is done to convert radius to diameter without changing all the code. |
---|
| 1842 | float r1 = d1 * .5f; |
---|
| 1843 | float r2 = d2 * .5f; |
---|
| 1844 | |
---|
| 1845 | //TODO: It would probably be good to think of another way of UV painting this, like "branch repeating" |
---|
| 1846 | int vbase = m_vert.Count(); |
---|
| 1847 | float maxr = max(r1, r2); |
---|
| 1848 | |
---|
| 1849 | AddVertex(vec3(0.f, 0.f, 0.f)); SetCurVertTexCoord(vec2(.5f, .5f)); SetCurVertTexCoord2(vec2(.5f, .5f)); |
---|
| 1850 | |
---|
| 1851 | mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f); |
---|
| 1852 | vec3 p1(r1, 0.f, 0.f), p2(r2, 0.f, 0.f); |
---|
| 1853 | vec3 uv1(0.f, 0.f, -.5f * ((float)r1 / maxr)), |
---|
| 1854 | uv2(0.f, 0.f, -.5f * ((float)r2 / maxr)); |
---|
| 1855 | |
---|
| 1856 | p2 = rotmat * p2; uv2 = rotmat * uv2; |
---|
| 1857 | rotmat = rotmat * rotmat; |
---|
| 1858 | |
---|
| 1859 | for (int i = 0; i < nbranches; i++) |
---|
| 1860 | { |
---|
| 1861 | AddVertex(p1); SetCurVertTexCoord(uv1.xz + vec2(.5f)); SetCurVertTexCoord2(uv1.xz + vec2(.5f)); |
---|
| 1862 | if (fade2) |
---|
| 1863 | SetCurVertColor(BD()->Color2()); |
---|
| 1864 | |
---|
| 1865 | AddVertex(p2); SetCurVertTexCoord(uv2.xz + vec2(.5f)); SetCurVertTexCoord2(uv2.xz + vec2(.5f)); |
---|
| 1866 | if (fade) |
---|
| 1867 | SetCurVertColor(BD()->Color2()); |
---|
| 1868 | |
---|
| 1869 | AppendQuad(0, 2 * i + 1, 2 * i + 2, (2 * i + 3) % (2 * nbranches), |
---|
| 1870 | vbase); |
---|
| 1871 | |
---|
| 1872 | p1 = rotmat * p1; uv1 = rotmat * uv1; |
---|
| 1873 | p2 = rotmat * p2; uv2 = rotmat * uv2; |
---|
| 1874 | } |
---|
| 1875 | } |
---|
| 1876 | |
---|
| 1877 | //----------------------------------------------------------------------------- |
---|
| 1878 | void EasyMesh::AppendExpandedStar(int nbranches, float d1, float d2, float extrad) |
---|
| 1879 | { |
---|
| 1880 | //XXX : This operation is done to convert radius to diameter without changing all the code. |
---|
| 1881 | float r1 = d1 * .5f; |
---|
| 1882 | float r2 = d2 * .5f; |
---|
| 1883 | float extrar = extrad * .5f; |
---|
| 1884 | |
---|
| 1885 | int vbase = m_vert.Count(); |
---|
| 1886 | float maxr = (float)max(max(r1, r2), max(r1 + extrar, r2 + extrar)); |
---|
| 1887 | |
---|
| 1888 | AddVertex(vec3(0.f, 0.f, 0.f)); SetCurVertTexCoord(vec2(.5f, .5f)); SetCurVertTexCoord2(vec2(.5f, .5f)); |
---|
| 1889 | |
---|
| 1890 | mat3 rotmat = mat3::rotate(180.0f / nbranches, 0.f, 1.f, 0.f); |
---|
| 1891 | vec3 p1(r1, 0.f, 0.f), p2(r2, 0.f, 0.f), |
---|
| 1892 | p3(r1 + extrar, 0.f, 0.f), p4(r2 + extrar, 0.f, 0.f);; |
---|
| 1893 | vec3 uv1(0.f, 0.f, -.5f * ((float)r1 / maxr)), |
---|
| 1894 | uv2(0.f, 0.f, -.5f * ((float)r2 / maxr)), |
---|
| 1895 | uv3(0.f, 0.f, -.5f * ((float)(r1 + extrar) / maxr)), |
---|
| 1896 | uv4(0.f, 0.f, -.5f * ((float)(r2 + extrar) / maxr)); |
---|
| 1897 | |
---|
| 1898 | p2 = rotmat * p2; uv2 = rotmat * uv2; |
---|
| 1899 | p4 = rotmat * p4; uv4 = rotmat * uv4; |
---|
| 1900 | rotmat = rotmat * rotmat; |
---|
| 1901 | |
---|
| 1902 | for (int i = 0; i < nbranches; i++) |
---|
| 1903 | { |
---|
| 1904 | AddVertex(p1); SetCurVertTexCoord(uv1.xz + vec2(.5f)); SetCurVertTexCoord2(uv1.xz + vec2(.5f)); |
---|
| 1905 | AddVertex(p2); SetCurVertTexCoord(uv2.xz + vec2(.5f)); SetCurVertTexCoord2(uv2.xz + vec2(.5f)); |
---|
| 1906 | AddVertex(p3); SetCurVertTexCoord(uv3.xz + vec2(.5f)); SetCurVertTexCoord2(uv3.xz + vec2(.5f)); SetCurVertColor(BD()->Color2()); |
---|
| 1907 | AddVertex(p4); SetCurVertTexCoord(uv4.xz + vec2(.5f)); SetCurVertTexCoord2(uv4.xz + vec2(.5f)); SetCurVertColor(BD()->Color2()); |
---|
| 1908 | |
---|
| 1909 | int j = (i + 1) % nbranches; |
---|
| 1910 | AppendQuad(0, 4 * i + 1, 4 * i + 2, 4 * j + 1, vbase); |
---|
| 1911 | AppendQuad(4 * i + 1, 4 * i + 3, 4 * i + 4, 4 * i + 2, vbase); |
---|
| 1912 | AppendQuad(4 * j + 1, 4 * i + 2, 4 * i + 4, 4 * j + 3, vbase); |
---|
| 1913 | |
---|
| 1914 | p1 = rotmat * p1; uv1 = rotmat * uv1; |
---|
| 1915 | p2 = rotmat * p2; uv2 = rotmat * uv2; |
---|
| 1916 | p3 = rotmat * p3; uv3 = rotmat * uv3; |
---|
| 1917 | p4 = rotmat * p4; uv4 = rotmat * uv4; |
---|
| 1918 | } |
---|
| 1919 | } |
---|
| 1920 | |
---|
| 1921 | //----------------------------------------------------------------------------- |
---|
| 1922 | void EasyMesh::AppendDisc(int nsides, float d, int fade) |
---|
| 1923 | { |
---|
| 1924 | //XXX : This operation is done to convert radius to diameter without changing all the code. |
---|
| 1925 | float r = d * .5f; |
---|
| 1926 | |
---|
| 1927 | int vbase = m_vert.Count(); |
---|
| 1928 | |
---|
| 1929 | AddVertex(vec3(0.f, 0.f, 0.f)); SetCurVertTexCoord(vec2(.5f, .5f)); SetCurVertTexCoord2(vec2(.5f, .5f)); |
---|
| 1930 | |
---|
| 1931 | mat3 rotmat = mat3::rotate(360.0f / nsides, 0.f, 1.f, 0.f); |
---|
| 1932 | vec3 p1(r, 0.f, 0.f); |
---|
| 1933 | vec3 uv(.5f, .0f, .0f); |
---|
| 1934 | |
---|
| 1935 | for (int i = 0; i < nsides; i++) |
---|
| 1936 | { |
---|
| 1937 | AddVertex(p1); SetCurVertTexCoord(uv.xz + vec2(.5f, .5f)); SetCurVertTexCoord2(uv.xz + vec2(.5f, .5f)); |
---|
| 1938 | if (fade) |
---|
| 1939 | SetCurVertColor(BD()->Color2()); |
---|
| 1940 | AppendTriangle(0, i + 1, ((i + 1) % nsides) + 1, vbase); |
---|
| 1941 | p1 = rotmat * p1; |
---|
| 1942 | uv = rotmat * uv; |
---|
| 1943 | } |
---|
| 1944 | } |
---|
| 1945 | |
---|
| 1946 | //----------------------------------------------------------------------------- |
---|
| 1947 | void EasyMesh::AppendSimpleTriangle(float d, int fade) |
---|
| 1948 | { |
---|
| 1949 | //XXX : This operation is done to convert radius to diameter without changing all the code. |
---|
| 1950 | float size = d * .5f; |
---|
| 1951 | |
---|
| 1952 | mat3 m = mat3::rotate(120.f, 0.f, 1.f, 0.f); |
---|
| 1953 | vec3 p(0.f, 0.f, size); |
---|
| 1954 | |
---|
| 1955 | AddVertex(p); SetCurVertTexCoord(vec2(.5f, 0.133975f)); SetCurVertTexCoord2(vec2(.5f, 0.133975f)); |
---|
| 1956 | p = m * p; |
---|
| 1957 | AddVertex(p); SetCurVertTexCoord(vec2(0.f, 1.f)); SetCurVertTexCoord2(vec2(0.f, 1.f)); |
---|
| 1958 | if (fade) |
---|
| 1959 | SetCurVertColor(BD()->Color2()); |
---|
| 1960 | p = m * p; |
---|
| 1961 | AddVertex(p); SetCurVertTexCoord(vec2(1.f, 1.f)); SetCurVertTexCoord2(vec2(1.f, 1.f)); |
---|
| 1962 | if (fade) |
---|
| 1963 | SetCurVertColor(BD()->Color2()); |
---|
| 1964 | |
---|
| 1965 | AppendTriangle(0, 1, 2, m_vert.Count() - 3); |
---|
| 1966 | } |
---|
| 1967 | |
---|
| 1968 | //----------------------------------------------------------------------------- |
---|
| 1969 | void EasyMesh::AppendSimpleQuad(float size, int fade) |
---|
| 1970 | { |
---|
| 1971 | AppendSimpleQuad(vec2(size * .5f), vec2(size * -.5f), 0.f, fade); |
---|
| 1972 | } |
---|
| 1973 | |
---|
| 1974 | //----------------------------------------------------------------------------- |
---|
| 1975 | void EasyMesh::AppendSimpleQuad(vec2 p1, vec2 p2, float z, int fade) |
---|
| 1976 | { |
---|
| 1977 | MeshType mt = MeshType::Quad; |
---|
| 1978 | MeshFaceType mft = MeshFaceType::QuadDefault; |
---|
| 1979 | |
---|
| 1980 | //-- |
---|
| 1981 | AddVertex(vec3(p2.x, z, -p1.y)); |
---|
| 1982 | TexCoordPos br = TexCoordPos::BR; |
---|
| 1983 | SetCurVertTexCoord(BD()->TexCoord(mt, br, mft)); |
---|
| 1984 | SetCurVertTexCoord2(BD()->TexCoord2(mt, br, mft)); |
---|
| 1985 | //-- |
---|
| 1986 | AddVertex(vec3(p2.x, z, -p2.y)); |
---|
| 1987 | TexCoordPos bl = TexCoordPos::BL; |
---|
| 1988 | SetCurVertTexCoord(BD()->TexCoord(mt, bl, mft)); |
---|
| 1989 | SetCurVertTexCoord2(BD()->TexCoord2(mt, bl, mft)); |
---|
| 1990 | //-- |
---|
| 1991 | AddVertex(vec3(p1.x, z, -p2.y)); |
---|
| 1992 | TexCoordPos tl = TexCoordPos::TL; |
---|
| 1993 | SetCurVertTexCoord(BD()->TexCoord(mt, tl, mft)); |
---|
| 1994 | SetCurVertTexCoord2(BD()->TexCoord2(mt, tl, mft)); |
---|
| 1995 | if (fade) SetCurVertColor(BD()->Color2()); |
---|
| 1996 | //-- |
---|
| 1997 | AddVertex(vec3(p1.x, z, -p1.y)); |
---|
| 1998 | TexCoordPos tr = TexCoordPos::TR; |
---|
| 1999 | SetCurVertTexCoord(BD()->TexCoord(mt, tr, mft)); |
---|
| 2000 | SetCurVertTexCoord2(BD()->TexCoord2(mt, tr, mft)); |
---|
| 2001 | if (fade) SetCurVertColor(BD()->Color2()); |
---|
| 2002 | |
---|
| 2003 | AppendQuad(0, 1, 2, 3, m_vert.Count() - 4); |
---|
| 2004 | ComputeNormals(m_indices.Count() - 6, 6); |
---|
| 2005 | } |
---|
| 2006 | |
---|
| 2007 | //----------------------------------------------------------------------------- |
---|
| 2008 | void EasyMesh::AppendCog(int nbsides, float h, float d10, float d20, |
---|
| 2009 | float d1, float d2, float d12, float d22, |
---|
| 2010 | float sidemul, int offset) |
---|
| 2011 | { |
---|
| 2012 | //XXX : This operation is done to convert radius to diameter without changing all the code. |
---|
| 2013 | float r10 = d10 * .5f; |
---|
| 2014 | float r20 = d20 * .5f; |
---|
| 2015 | float r1 = d1 * .5f; |
---|
| 2016 | float r2 = d2 * .5f; |
---|
| 2017 | float r12 = d12 * .5f; |
---|
| 2018 | float r22 = d22 * .5f; |
---|
| 2019 | |
---|
| 2020 | int ibase = m_indices.Count(); |
---|
| 2021 | int vbase = m_vert.Count(); |
---|
| 2022 | |
---|
| 2023 | /* FIXME: enforce this some other way */ |
---|
| 2024 | if (r12 < 0) |
---|
| 2025 | h = -h; |
---|
| 2026 | |
---|
| 2027 | mat3 rotmat = mat3::rotate(180.0f / nbsides, 0.f, 1.f, 0.f); |
---|
| 2028 | mat3 smat1 = mat3::rotate(sidemul * 180.0f / nbsides, 0.f, 1.f, 0.f); |
---|
| 2029 | mat3 smat2 = mat3::rotate(sidemul * -360.0f / nbsides, 0.f, 1.f, 0.f); |
---|
| 2030 | |
---|
| 2031 | vec3 p[12]; |
---|
| 2032 | |
---|
| 2033 | //Upper points |
---|
| 2034 | p[0] = vec3(r10, h * .5f, 0.f); |
---|
| 2035 | p[1] = rotmat * p[0]; |
---|
| 2036 | p[2] = vec3(r1, h * .5f, 0.f); |
---|
| 2037 | p[3] = rotmat * p[2]; |
---|
| 2038 | p[4] = smat1 * (rotmat * vec3(r1 + r12, h * .5f, 0.f)); |
---|
| 2039 | p[5] = smat2 * (rotmat * p[4]); |
---|
| 2040 | |
---|
| 2041 | //Lower points |
---|
| 2042 | p[6] = vec3(r20, h * -.5f, 0.f); |
---|
| 2043 | p[7] = rotmat * p[6]; |
---|
| 2044 | p[8] = vec3(r2, h * -.5f, 0.f); |
---|
| 2045 | p[9] = rotmat * p[8]; |
---|
| 2046 | p[10] = smat1 * (rotmat * vec3(r2 + r22, h * -.5f, 0.f)); |
---|
| 2047 | p[11] = smat2 * (rotmat * p[10]); |
---|
| 2048 | |
---|
| 2049 | if (offset & 1) |
---|
| 2050 | for (int n = 0; n < 12; n++) |
---|
| 2051 | p[n] = rotmat * p[n]; |
---|
| 2052 | |
---|
| 2053 | rotmat = rotmat * rotmat; |
---|
| 2054 | |
---|
| 2055 | //UV base computation |
---|
| 2056 | float maxr = max(max(r1 + r12, r2 + r22), max(r10, r20)); |
---|
| 2057 | float InLn = length(p[1] - p[0]); |
---|
| 2058 | float CogLn[8] = { .0f, .0f, .0f, .0f, .0f, .0f, .0f, .0f }; |
---|
| 2059 | for (int i = 0; i < 3; i++) |
---|
| 2060 | { |
---|
| 2061 | for (int j = 0, k = 2; j < 8 && k < 12; j += 4, k += 6) |
---|
| 2062 | { |
---|
| 2063 | CogLn[j + i] = length(p[k + i + 1] - p[k + i]); |
---|
| 2064 | CogLn[j + 3] += CogLn[j + i]; |
---|
| 2065 | if (i == 1) //Add 3to4 twice since it's automatically completed by +1 loop. |
---|
| 2066 | CogLn[j + 3] += CogLn[j + i]; |
---|
| 2067 | } |
---|
| 2068 | } |
---|
| 2069 | |
---|
| 2070 | //Choose the biggest cog length |
---|
| 2071 | int CogSrc = (CogLn[7] > CogLn[3])?(4):(0); |
---|
| 2072 | CogLn[3] = CogLn[CogSrc + 3]; |
---|
| 2073 | for (int i = 0; i < 3; i++) |
---|
| 2074 | CogLn[i] = CogLn[CogSrc + i] / CogLn[CogSrc + 3]; |
---|
| 2075 | |
---|
| 2076 | //Calculate Cog Modifiers |
---|
| 2077 | vec2 InUV[2] = { vec2(.0f), vec2(.5f) }; |
---|
| 2078 | vec2 CogUV[2] = { vec2(.0f), vec2(.5f) }; |
---|
| 2079 | vec2 upadd = vec2(.25f, .75f); |
---|
| 2080 | vec2 lowadd = vec2(.75f, .75f); |
---|
| 2081 | { |
---|
| 2082 | if (h < InLn) |
---|
| 2083 | { |
---|
| 2084 | InUV[0].x = 1.0f; |
---|
| 2085 | InUV[0].y = h / InLn; |
---|
| 2086 | InUV[1].x = .0f; |
---|
| 2087 | InUV[1].y -= InUV[0].y * .5f; |
---|
| 2088 | } |
---|
| 2089 | else |
---|
| 2090 | { |
---|
| 2091 | InUV[0].x = InLn / h; |
---|
| 2092 | InUV[0].y = 1.0f; |
---|
| 2093 | InUV[1].x -= InUV[0].x * .5f; |
---|
| 2094 | InUV[1].y = .0f; |
---|
| 2095 | } |
---|
| 2096 | if (h < CogLn[3]) |
---|
| 2097 | { |
---|
| 2098 | CogUV[0].x = 1.0f; |
---|
| 2099 | CogUV[0].y = h / CogLn[3]; |
---|
| 2100 | CogUV[1].x = .0f; |
---|
| 2101 | CogUV[1].y -= CogUV[0].y * .5f; |
---|
| 2102 | } |
---|
| 2103 | else |
---|
| 2104 | { |
---|
| 2105 | CogUV[0].x = CogLn[3] / h; |
---|
| 2106 | CogUV[0].y = 1.0f; |
---|
| 2107 | CogUV[1].x -= CogUV[0].x * .5f; |
---|
| 2108 | CogUV[1].y = .0f; |
---|
| 2109 | } |
---|
| 2110 | if (InUV[0].x + CogUV[0].x < .5f) |
---|
| 2111 | { |
---|
| 2112 | InUV[1].x = .0f; |
---|
| 2113 | CogUV[1].x = .5f - CogUV[0].x; |
---|
| 2114 | upadd = vec2(.75f, .25f); |
---|
| 2115 | lowadd = vec2(.75f, .75f); |
---|
| 2116 | } |
---|
| 2117 | else if (InUV[0].y + CogUV[0].y < .5f) |
---|
| 2118 | { |
---|
| 2119 | InUV[1].y = .0f; |
---|
| 2120 | CogUV[1].y = .5f - CogUV[0].y; |
---|
| 2121 | } |
---|
| 2122 | else |
---|
| 2123 | { |
---|
| 2124 | InUV[0] *= .5f; |
---|
| 2125 | InUV[1] *= .5f; |
---|
| 2126 | CogUV[0] *= .5f; |
---|
| 2127 | CogUV[1] *= .5f; |
---|
| 2128 | InUV[1] += vec2(.5f, .0f); |
---|
| 2129 | } |
---|
| 2130 | } |
---|
| 2131 | |
---|
| 2132 | //Build UV tab |
---|
| 2133 | vec2 uv[12]; float CogSz; |
---|
| 2134 | //Upper points |
---|
| 2135 | CogSz = 1.0f - CogLn[1]; |
---|
| 2136 | uv[0] = vec2(0.f, 0.f) * InUV[0] + InUV[1]; |
---|
| 2137 | uv[1] = vec2(1.f, 0.f) * InUV[0] + InUV[1]; |
---|
| 2138 | uv[5] = vec2(CogSz, 0.f) * CogUV[0] + CogUV[1]; CogSz -= CogLn[2]; |
---|
| 2139 | uv[4] = vec2(CogSz, 0.f) * CogUV[0] + CogUV[1]; CogSz -= CogLn[1]; |
---|
| 2140 | uv[3] = vec2(CogSz, 0.f) * CogUV[0] + CogUV[1]; CogSz -= CogLn[0]; |
---|
| 2141 | uv[2] = vec2(0.f, 0.f) * CogUV[0] + CogUV[1]; |
---|
| 2142 | |
---|
| 2143 | //Lower points |
---|
| 2144 | CogSz = 1.0f - CogLn[1]; |
---|
| 2145 | uv[6] = vec2(0.f, 1.f) * InUV[0] + InUV[1]; |
---|
| 2146 | uv[7] = vec2(1.f, 1.f) * InUV[0] + InUV[1]; |
---|
| 2147 | uv[11] = vec2(CogSz, 1.f) * CogUV[0] + CogUV[1]; CogSz -= CogLn[2]; |
---|
| 2148 | uv[10] = vec2(CogSz, 1.f) * CogUV[0] + CogUV[1]; CogSz -= CogLn[1]; |
---|
| 2149 | uv[ 9] = vec2(CogSz, 1.f) * CogUV[0] + CogUV[1]; CogSz -= CogLn[0]; |
---|
| 2150 | uv[ 8] = vec2(0.f, 1.f) * CogUV[0] + CogUV[1]; |
---|
| 2151 | |
---|
| 2152 | //Gear generation loop |
---|
| 2153 | for (int i = 0; i < nbsides; i++) |
---|
| 2154 | { |
---|
| 2155 | int j = 3 * 12 * i, |
---|
| 2156 | k = 3 * 12 * ((i + 1) % nbsides); |
---|
| 2157 | |
---|
| 2158 | int q[] = { /* The top and bottom faces */ |
---|
| 2159 | j, j, j, j, |
---|
| 2160 | j, j, j, j, |
---|
| 2161 | j, j, k, k, |
---|
| 2162 | k, k, j, j, |
---|
| 2163 | j, j, j, k, |
---|
| 2164 | k, j, j, j, |
---|
| 2165 | /* The inner side quads */ |
---|
| 2166 | j, j, j, j, |
---|
| 2167 | j, k, k, j, |
---|
| 2168 | /* The outer side quads */ |
---|
| 2169 | j, j, j, j, |
---|
| 2170 | j, j, j, j, |
---|
| 2171 | j, j, j, j, |
---|
| 2172 | k, j, j, k |
---|
| 2173 | }; |
---|
| 2174 | int m[] = { /* The top and bottom faces */ |
---|
| 2175 | 0, 2, 3, 1, |
---|
| 2176 | 7, 9, 8, 6, |
---|
| 2177 | 1, 3, 2, 0, |
---|
| 2178 | 6, 8, 9, 7, |
---|
| 2179 | 3, 4, 5, 2, |
---|
| 2180 | 8, 11, 10, 9, |
---|
| 2181 | /* The inner side quads */ |
---|
| 2182 | 0, 1, 7, 6, |
---|
| 2183 | 1, 0, 6, 7, |
---|
| 2184 | /* The outer side quads */ |
---|
| 2185 | 3, 2, 8, 9, |
---|
| 2186 | 4, 3, 9, 10, |
---|
| 2187 | 5, 4, 10, 11, |
---|
| 2188 | 2, 5, 11, 8 |
---|
| 2189 | }; |
---|
| 2190 | int a[] = { /* The top and bottom faces */ |
---|
| 2191 | 0, 0, 0, 0, |
---|
| 2192 | 0, 0, 0, 0, |
---|
| 2193 | 0, 0, 0, 0, |
---|
| 2194 | 0, 0, 0, 0, |
---|
| 2195 | 0, 0, 0, 0, |
---|
| 2196 | 0, 0, 0, 0, |
---|
| 2197 | /* The inner side quads */ |
---|
| 2198 | 1, 1, 1, 1, |
---|
| 2199 | 2, 2, 2, 2, |
---|
| 2200 | /* The outer side quads */ |
---|
| 2201 | 1, 1, 1, 1, |
---|
| 2202 | 1, 2, 2, 1, |
---|
| 2203 | 1, 2, 2, 1, |
---|
| 2204 | 2, 2, 2, 2 |
---|
| 2205 | }; |
---|
| 2206 | |
---|
| 2207 | /* Each vertex will share three faces, so three different |
---|
| 2208 | * normals, therefore we add each vertex three times. */ |
---|
| 2209 | for (int n = 0; n < 3 * 12; n++) |
---|
| 2210 | { |
---|
| 2211 | int d = n / 3; |
---|
| 2212 | int e = d % 6; |
---|
| 2213 | AddVertex(p[d]); |
---|
| 2214 | if (n % 3 == 0) //Top-Bottom logic |
---|
| 2215 | { |
---|
| 2216 | vec2 tmp = (p[d].xz / maxr); |
---|
| 2217 | vec2 add; |
---|
| 2218 | if (d >= 6) |
---|
| 2219 | { |
---|
| 2220 | tmp *= -1.0f; |
---|
| 2221 | add = lowadd; |
---|
| 2222 | } |
---|
| 2223 | else |
---|
| 2224 | add = upadd; |
---|
| 2225 | SetCurVertTexCoord(tmp * vec2(.25f) + add); |
---|
| 2226 | SetCurVertTexCoord2(tmp * vec2(.25f) + add); |
---|
| 2227 | } |
---|
| 2228 | else if (e == 0 || e == 1) //inner Logic |
---|
| 2229 | { |
---|
| 2230 | SetCurVertTexCoord(uv[d]); |
---|
| 2231 | SetCurVertTexCoord2(uv[d]); |
---|
| 2232 | } |
---|
| 2233 | else //Cog logic |
---|
| 2234 | { |
---|
| 2235 | if (e == 2 && n % 3 == 2) |
---|
| 2236 | { |
---|
| 2237 | SetCurVertTexCoord(vec2(1.f, (d == 2)?(0.f):(1.f)) * CogUV[0] + CogUV[1]); |
---|
| 2238 | SetCurVertTexCoord2(vec2(1.f, (d == 2)?(0.f):(1.f)) * CogUV[0] + CogUV[1]); |
---|
| 2239 | } |
---|
| 2240 | else |
---|
| 2241 | { |
---|
| 2242 | SetCurVertTexCoord(uv[d]); |
---|
| 2243 | SetCurVertTexCoord2(uv[d]); |
---|
| 2244 | } |
---|
| 2245 | } |
---|
| 2246 | if (d >= 6) |
---|
| 2247 | SetCurVertColor(BD()->Color2()); |
---|
| 2248 | } |
---|
| 2249 | |
---|
| 2250 | int l = -4; |
---|
| 2251 | while ((l += 4) < 48) |
---|
| 2252 | AppendQuad(q[l + 0] + m[l + 0] * 3 + a[l + 0], |
---|
| 2253 | q[l + 1] + m[l + 1] * 3 + a[l + 1], |
---|
| 2254 | q[l + 2] + m[l + 2] * 3 + a[l + 2], |
---|
| 2255 | q[l + 3] + m[l + 3] * 3 + a[l + 3], |
---|
| 2256 | vbase); |
---|
| 2257 | |
---|
| 2258 | for (int n = 0; n < 12; n++) |
---|
| 2259 | p[n] = rotmat * p[n]; |
---|
| 2260 | } |
---|
| 2261 | |
---|
| 2262 | ComputeNormals(ibase, m_indices.Count() - ibase); |
---|
| 2263 | } |
---|
| 2264 | |
---|
| 2265 | //----------------------------------------------------------------------------- |
---|
| 2266 | void EasyMesh::Chamfer(float f) |
---|
| 2267 | { |
---|
| 2268 | int vlen = m_vert.Count() - m_cursors.Last().m1; |
---|
| 2269 | int ilen = m_indices.Count() - m_cursors.Last().m2; |
---|
| 2270 | |
---|
| 2271 | /* Step 1: enumerate all faces. This is done by merging triangles |
---|
| 2272 | * that are coplanar and share an edge. */ |
---|
| 2273 | int *triangle_classes = new int[ilen / 3]; |
---|
| 2274 | for (int i = 0; i < ilen / 3; i++) |
---|
| 2275 | triangle_classes[i] = -1; |
---|
| 2276 | |
---|
| 2277 | for (int i = 0; i < ilen / 3; i++) |
---|
| 2278 | { |
---|
| 2279 | |
---|
| 2280 | } |
---|
| 2281 | |
---|
| 2282 | /* Fun shit: reduce all triangles */ |
---|
| 2283 | int *vertices = new int[vlen]; |
---|
| 2284 | memset(vertices, 0, vlen * sizeof(int)); |
---|
| 2285 | for (int i = 0; i < ilen; i++) |
---|
| 2286 | vertices[m_indices[i]]++; |
---|
| 2287 | |
---|
| 2288 | for (int i = 0; i < ilen / 3; i++) |
---|
| 2289 | |
---|
| 2290 | { |
---|
| 2291 | #if 0 |
---|
| 2292 | if (vertices[m_indices[i * 3]] > 1) |
---|
| 2293 | continue; |
---|
| 2294 | if (vertices[m_indices[i * 3 + 1]] > 1) |
---|
| 2295 | continue; |
---|
| 2296 | if (vertices[m_indices[i * 3 + 2]] > 1) |
---|
| 2297 | continue; |
---|
| 2298 | #endif |
---|
| 2299 | |
---|
| 2300 | vec3 bary = 1.f / 3.f * (m_vert[m_indices[i * 3]].m_coord + |
---|
| 2301 | m_vert[m_indices[i * 3 + 1]].m_coord + |
---|
| 2302 | m_vert[m_indices[i * 3 + 2]].m_coord); |
---|
| 2303 | for (int k = 0; k < 3; k++) |
---|
| 2304 | { |
---|
| 2305 | vec3 &p = m_vert[m_indices[i * 3 + k]].m_coord; |
---|
| 2306 | p -= normalize(p - bary) * f; |
---|
| 2307 | } |
---|
| 2308 | } |
---|
| 2309 | } |
---|
| 2310 | |
---|
| 2311 | //----------------------------------------------------------------------------- |
---|
| 2312 | void EasyMesh::SplitTriangles(int pass) { SplitTriangles(pass, nullptr); } |
---|
| 2313 | |
---|
| 2314 | //----------------------------------------------------------------------------- |
---|
| 2315 | void EasyMesh::SplitTriangles(int pass, VertexDictionnary *vert_dict) |
---|
| 2316 | { |
---|
| 2317 | while (pass--) |
---|
| 2318 | { |
---|
| 2319 | int trimax = m_indices.Count(); |
---|
| 2320 | for (int i = m_cursors.Last().m2; i < trimax; i += 3) |
---|
| 2321 | { |
---|
| 2322 | int vbase = m_vert.Count(); |
---|
| 2323 | int j = -1; |
---|
| 2324 | while (++j < 3) |
---|
| 2325 | { |
---|
| 2326 | AddLerpVertex(m_indices[i + j], m_indices[i + (j + 1) % 3], .5f); |
---|
| 2327 | if (vert_dict) |
---|
| 2328 | vert_dict->AddVertex(vbase + j, m_vert[vbase + j].m_coord); |
---|
| 2329 | } |
---|
| 2330 | //Add new triangles |
---|
| 2331 | AppendTriangle(vbase, m_indices[i + 1], vbase + 1, 0); |
---|
| 2332 | AppendTriangle(vbase + 2, vbase + 1, m_indices[i + 2], 0); |
---|
| 2333 | AppendTriangle(vbase, vbase + 1, vbase + 2, 0); |
---|
| 2334 | //Change current triangle |
---|
| 2335 | m_indices[i + 1] = vbase; |
---|
| 2336 | m_indices[i + 2] = vbase + 2; |
---|
| 2337 | } |
---|
| 2338 | } |
---|
| 2339 | ComputeNormals(m_cursors.Last().m2, m_indices.Count() - m_cursors.Last().m2); |
---|
| 2340 | } |
---|
| 2341 | |
---|
| 2342 | //----------------------------------------------------------------------------- |
---|
| 2343 | //TODO : Add an half-edges implementation to refine smooth. |
---|
| 2344 | //TODO : Smooth should only use connected vertices that are on edges of the mesh (See box). |
---|
| 2345 | void EasyMesh::SmoothMesh(int main_pass, int split_per_main_pass, int smooth_per_main_pass) |
---|
| 2346 | { |
---|
| 2347 | VertexDictionnary vert_dict; |
---|
| 2348 | Array<vec3> smooth_buf[2]; |
---|
| 2349 | Array<int> master_list; |
---|
| 2350 | Array<int> matching_ids; |
---|
| 2351 | Array<int> connected_vert; |
---|
| 2352 | int smbuf = 0; |
---|
| 2353 | |
---|
| 2354 | for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++) |
---|
| 2355 | vert_dict.AddVertex(i, m_vert[i].m_coord); |
---|
| 2356 | |
---|
| 2357 | while (main_pass--) |
---|
| 2358 | { |
---|
| 2359 | int split_pass = split_per_main_pass; |
---|
| 2360 | int smooth_pass = smooth_per_main_pass; |
---|
| 2361 | |
---|
| 2362 | SplitTriangles(split_pass, &vert_dict); |
---|
| 2363 | |
---|
| 2364 | matching_ids.Reserve(m_vert.Count() - m_cursors.Last().m1); |
---|
| 2365 | connected_vert.Reserve(m_vert.Count() - m_cursors.Last().m1); |
---|
| 2366 | smooth_buf[0].Resize(m_vert.Count() - m_cursors.Last().m1); |
---|
| 2367 | smooth_buf[1].Resize(m_vert.Count() - m_cursors.Last().m1); |
---|
| 2368 | |
---|
| 2369 | for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++) |
---|
| 2370 | smooth_buf[smbuf][i - m_cursors.Last().m1] = m_vert[i].m_coord; |
---|
| 2371 | |
---|
| 2372 | while (smooth_pass--) |
---|
| 2373 | { |
---|
| 2374 | master_list.Empty(); |
---|
| 2375 | if (vert_dict.GetMasterList(master_list)) |
---|
| 2376 | { |
---|
| 2377 | for (int i = 0; i < master_list.Count(); i++) |
---|
| 2378 | { |
---|
| 2379 | connected_vert.Empty(); |
---|
| 2380 | if (vert_dict.FindConnectedVertices(master_list[i], m_indices, m_cursors.Last().m2, connected_vert)) |
---|
| 2381 | { |
---|
| 2382 | //Calculate vertices sum |
---|
| 2383 | vec3 vert_sum = vec3(.0f); |
---|
| 2384 | for (int j = 0; j < connected_vert.Count(); j++) |
---|
| 2385 | vert_sum += smooth_buf[smbuf][connected_vert[j] - m_cursors.Last().m1]; |
---|
| 2386 | |
---|
| 2387 | //Calculate new master vertex |
---|
| 2388 | float n = (float)connected_vert.Count(); |
---|
| 2389 | //b(n) = 5/4 - pow(3 + 2 * cos(2.f * F_PI / n), 2) / 32 |
---|
| 2390 | float beta = 3.f + 2.f * cos(2.f * F_PI / n); |
---|
| 2391 | beta = 5.f / 4.f - beta * beta / 32.f; |
---|
| 2392 | //a(n) = n * (1 - b(n)) / b(n) |
---|
| 2393 | float alpha = (n * (1 - beta)) / beta; |
---|
| 2394 | //V = (a(n) * v + v1 + ... + vn) / (a(n) + n) |
---|
| 2395 | vec3 new_vert = (alpha * smooth_buf[smbuf][master_list[i] - m_cursors.Last().m1] + vert_sum) / (alpha + n); |
---|
| 2396 | |
---|
| 2397 | //Set all matching vertices to new value |
---|
| 2398 | matching_ids.Empty(); |
---|
| 2399 | matching_ids << master_list[i]; |
---|
| 2400 | vert_dict.FindMatchingVertices(master_list[i], matching_ids); |
---|
| 2401 | for (int j = 0; j < matching_ids.Count(); j++) |
---|
| 2402 | smooth_buf[1 - smbuf][matching_ids[j] - m_cursors.Last().m1] = new_vert; |
---|
| 2403 | } |
---|
| 2404 | } |
---|
| 2405 | } |
---|
| 2406 | smbuf = 1 - smbuf; |
---|
| 2407 | } |
---|
| 2408 | |
---|
| 2409 | for (int i = 0; i < smooth_buf[smbuf].Count(); i++) |
---|
| 2410 | m_vert[i + m_cursors.Last().m1].m_coord = smooth_buf[smbuf][i]; |
---|
| 2411 | } |
---|
| 2412 | } |
---|
| 2413 | |
---|
| 2414 | } /* namespace lol */ |
---|