Useage : "...[.... csg*]" equals "current mesh -CSG- the mesh in the braces". Keywords : CsgUnion<csgu>, CsgSubstract<csgs>, CsgAnd<csga>, CsgXor<csgx> TODO : cleanup useless code. TODO : Some bugs are still present, some face that disappear should not. TODO : Correct epsilon useage (see geometry files). TODO : Coplanar face are not handled -at all-. TODO : Vertex count goes through the roof in case of a Xor.legacy
| @@ -30,6 +30,7 @@ liblol_a_SOURCES = \ | |||
| eglapp.cpp eglapp.h \ | |||
| \ | |||
| easymesh/easymesh.cpp easymesh/easymesh.h \ | |||
| easymesh/csgbsp.cpp easymesh/csgbsp.h \ | |||
| easymesh/shiny.lolfx \ | |||
| easymesh/easymesh-compiler.cpp easymesh/easymesh-compiler.h \ | |||
| generated/easymesh-parser.cpp generated/easymesh-parser.h \ | |||
| @@ -132,6 +132,7 @@ static inline int isnan(float f) | |||
| #include "mesh/mesh.h" | |||
| #include "image/image.h" | |||
| #include "application/application.h" | |||
| #include "easymesh/csgbsp.h" | |||
| #include "easymesh/easymesh.h" | |||
| // Managers | |||
| @@ -0,0 +1,553 @@ | |||
| // | |||
| // Lol Engine | |||
| // | |||
| // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net> | |||
| // (c) 2010-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com> | |||
| // This program is free software; you can redistribute it and/or | |||
| // modify it under the terms of the Do What The Fuck You Want To | |||
| // Public License, Version 2, as published by Sam Hocevar. See | |||
| // http://www.wtfpl.net/ for more details. | |||
| // | |||
| // | |||
| // The EasyMesh class | |||
| // ------------------ | |||
| // | |||
| #if defined HAVE_CONFIG_H | |||
| # include "config.h" | |||
| #endif | |||
| #if defined _XBOX | |||
| # define _USE_MATH_DEFINES /* for M_PI */ | |||
| # include <xtl.h> | |||
| # undef near /* Fuck Microsoft */ | |||
| # undef far /* Fuck Microsoft again */ | |||
| #elif defined _WIN32 | |||
| # define _USE_MATH_DEFINES /* for M_PI */ | |||
| # define WIN32_LEAN_AND_MEAN | |||
| # include <windows.h> | |||
| # undef near /* Fuck Microsoft */ | |||
| # undef far /* Fuck Microsoft again */ | |||
| #endif | |||
| #include "core.h" | |||
| namespace lol | |||
| { | |||
| int CsgBsp::AddLeaf(int leaf_type, vec3 origin, vec3 normal, int above_idx) | |||
| { | |||
| if (leaf_type > 2 && leaf_type < -1) | |||
| return -1; | |||
| if ((m_tree.Count() == 0 && above_idx == -1) || | |||
| (above_idx >= 0 && | |||
| above_idx < m_tree.Count() && | |||
| leaf_type > LEAF_CURRENT && | |||
| leaf_type < LEAF_ABOVE && | |||
| m_tree[above_idx].m_leaves[leaf_type] == -1)) | |||
| { | |||
| if (m_tree.Count() != 0) | |||
| m_tree[above_idx].m_leaves[leaf_type] = m_tree.Count(); | |||
| m_tree.Push(CsgBspLeaf(origin, normal, above_idx)); | |||
| return m_tree.Count() - 1; | |||
| } | |||
| return -1; | |||
| } | |||
| int CsgBsp::TestPoint(int leaf_idx, vec3 point) | |||
| { | |||
| if (leaf_idx >= 0 && leaf_idx < m_tree.Count()) | |||
| { | |||
| vec3 p2o = point - m_tree[leaf_idx].m_origin; | |||
| if (length(p2o) < CSG_EPSILON) | |||
| return LEAF_CURRENT; | |||
| float p2o_dot = dot(normalize(p2o), m_tree[leaf_idx].m_normal); | |||
| if (p2o_dot > CSG_EPSILON) | |||
| return LEAF_FRONT; | |||
| else if (p2o_dot < -CSG_EPSILON) | |||
| return LEAF_BACK; | |||
| } | |||
| return LEAF_CURRENT; | |||
| } | |||
| void CsgBsp::AddTriangleToTree(int const &tri_idx, vec3 const &tri_v0, vec3 const &tri_v1, vec3 const &tri_v2) | |||
| { | |||
| //<Leaf_Id, v0, v1, v2> | |||
| Array< int, vec3, vec3, vec3 > tri_to_process; | |||
| //<FW/BW, Leaf_Id, v0, v1, v2, twin_leaf> | |||
| Array< int, int, vec3, vec3, vec3, int > Leaf_to_add; | |||
| //Tree is empty, so this leaf is the first | |||
| if (m_tree.Count() == 0) | |||
| { | |||
| AddLeaf(LEAF_CURRENT, tri_v0, cross(normalize(tri_v1 - tri_v0), normalize(tri_v2 - tri_v1)), LEAF_CURRENT); | |||
| m_tree.Last().m_tri_list.Push(tri_idx, tri_v0, tri_v1, tri_v2); | |||
| return; | |||
| } | |||
| tri_to_process.Reserve(20); | |||
| tri_to_process.Push(0, tri_v0, tri_v1, tri_v2); | |||
| while (tri_to_process.Count()) | |||
| { | |||
| int leaf_idx = tri_to_process.Last().m1; | |||
| vec3 v[3] = { tri_to_process.Last().m2, tri_to_process.Last().m3, tri_to_process.Last().m4 }; | |||
| int res_nb[3] = { 0, 0, 0 }; | |||
| int res_side[3] = { -1, -1, -1 }; | |||
| //Check where each point is located | |||
| for (int i = 0; i < 3; i++) | |||
| { | |||
| int result = TestPoint(leaf_idx, v[i]); | |||
| if (result != LEAF_CURRENT) | |||
| { | |||
| res_nb[result]++; | |||
| res_side[i] = result; | |||
| } | |||
| } | |||
| //Points are located on each sides, let's do the mumbo-jumbo | |||
| if (res_nb[LEAF_BACK] && res_nb[LEAF_FRONT]) | |||
| { | |||
| //there are two intersections, no more. | |||
| vec3 isec_v[2] = { vec3(.0f), vec3(.0f) }; | |||
| int isec_i[2] = { 0, 0 }; | |||
| int isec_base = 0; | |||
| int isec_idx = 0; | |||
| for (int i = 0; i < 3; i++) | |||
| { | |||
| vec3 ray = v[(i + 1) % 3] - v[i]; | |||
| if (RayIsectPlane(v[i], v[(i + 1) % 3], | |||
| m_tree[leaf_idx].m_origin, m_tree[leaf_idx].m_normal, | |||
| isec_v[isec_idx])) | |||
| isec_i[isec_idx++] = i; | |||
| else | |||
| isec_base = i; | |||
| } | |||
| int v_idx0 = (isec_base == 1)?(1):(0); | |||
| int v_idx1 = (isec_base == 1)?(0):(1); | |||
| int leaf_type = res_side[(isec_base + 2) % 3]; | |||
| tri_to_process.Pop(); | |||
| #if 1 | |||
| if (m_tree[leaf_idx].m_leaves[leaf_type] == LEAF_CURRENT) | |||
| Leaf_to_add.Push(leaf_type, leaf_idx, v[((isec_base + 2) % 3)], isec_v[v_idx1], isec_v[v_idx0], -1); | |||
| else | |||
| tri_to_process.Push(leaf_idx, v[((isec_base + 2) % 3)], isec_v[v_idx1], isec_v[v_idx0]); | |||
| if (m_tree[leaf_idx].m_leaves[1 - leaf_type] == LEAF_CURRENT) | |||
| { | |||
| Leaf_to_add.Push(1 - leaf_type, leaf_idx, v[isec_base], v[((isec_base + 1) % 3)], isec_v[v_idx0], -1); | |||
| Leaf_to_add.Push(1 - leaf_type, leaf_idx, v[isec_base], isec_v[v_idx0], isec_v[v_idx1], Leaf_to_add.Count() - 1); | |||
| } | |||
| else | |||
| { | |||
| tri_to_process.Push(m_tree[leaf_idx].m_leaves[1 - leaf_type], v[isec_base], v[((isec_base + 1) % 3)], isec_v[v_idx0]); | |||
| tri_to_process.Push(m_tree[leaf_idx].m_leaves[1 - leaf_type], v[isec_base], isec_v[v_idx0], isec_v[v_idx1]); | |||
| } | |||
| #else | |||
| vec3 new_v[9] = { v[((isec_base + 2) % 3)], isec_v[v_idx1], isec_v[v_idx0], | |||
| v[isec_base], v[((isec_base + 1) % 3)], isec_v[v_idx0], | |||
| v[isec_base], isec_v[v_idx0], isec_v[v_idx1] }; | |||
| //Error check : Skip the triangle where two points are on the same location. | |||
| //it fixes the problem of having an intersection with one of the isec-point being on one of the triangle vertices. | |||
| //(the problem being a very funny infinite loop) | |||
| for(int k = 0; k < 9; k += 3) | |||
| { | |||
| bool skip_tri = false; | |||
| for(int l = 0; l < 3; l++) | |||
| { | |||
| if (length(new_v[k + l] - new_v[k + (l + 1) % 3]) < CSG_EPSILON) | |||
| { | |||
| skip_tri = true; | |||
| break; | |||
| } | |||
| } | |||
| if (skip_tri) | |||
| continue; | |||
| tri_to_process.Push(0, new_v[k], new_v[k + 1], new_v[k + 2]); | |||
| } | |||
| #endif | |||
| } | |||
| //All points are on one side, transfer to the next leaf | |||
| else if (res_nb[LEAF_BACK] || res_nb[LEAF_FRONT]) | |||
| { | |||
| int new_leaf_type = ((res_nb[LEAF_FRONT])?(LEAF_FRONT):(LEAF_BACK)); | |||
| int new_leaf = m_tree[leaf_idx].m_leaves[new_leaf_type]; | |||
| //No leaf exist, so add a new one | |||
| if (new_leaf == LEAF_CURRENT) | |||
| { | |||
| tri_to_process.Pop(); | |||
| Leaf_to_add.Push(new_leaf_type, leaf_idx, v[0], v[1], v[2], -1); | |||
| } | |||
| else | |||
| tri_to_process.Last().m1 = new_leaf; | |||
| } | |||
| //All points are on the current leaf, add the tri_idx to the list of this leaf. | |||
| else | |||
| { | |||
| tri_to_process.Pop(); | |||
| bool already_exist = false; | |||
| for (int i = 0; !already_exist && i < m_tree[leaf_idx].m_tri_list.Count(); i++) | |||
| already_exist = (m_tree[leaf_idx].m_tri_list[i].m1 == tri_idx); | |||
| if (!already_exist) | |||
| m_tree[leaf_idx].m_tri_list.Push(tri_idx, tri_v0, tri_v1, tri_v2); | |||
| } | |||
| } | |||
| //Add all leaves to the tree. | |||
| for (int i = 0; i < Leaf_to_add.Count(); i++) | |||
| { | |||
| //If we had it to an already existing leaf. | |||
| if (Leaf_to_add[i].m2 < m_tree.Count() && m_tree[Leaf_to_add[i].m2].m_leaves[Leaf_to_add[i].m1] == LEAF_CURRENT) | |||
| { | |||
| AddLeaf(Leaf_to_add[i].m1, tri_v0, cross(normalize(tri_v1 - tri_v0), normalize(tri_v2 - tri_v1)), Leaf_to_add[i].m2); | |||
| m_tree.Last().m_tri_list.Push(tri_idx, tri_v0, tri_v1, tri_v2); | |||
| } | |||
| /* | |||
| if (Leaf_to_add[i].m6 == -1) | |||
| { | |||
| AddLeaf(Leaf_to_add[i].m1, tri_v0, cross(normalize(tri_v1 - tri_v0), normalize(tri_v2 - tri_v1)), Leaf_to_add[i].m2); | |||
| m_tree.Last().m_tri_list.Push(tri_idx, tri_v0, tri_v1, tri_v2); | |||
| } | |||
| else | |||
| m_tree[Leaf_to_add[i].m6].m_tri_list.Push(tri_idx, tri_v0, tri_v1, tri_v2); | |||
| */ | |||
| } | |||
| } | |||
| //return 0 when no split has been done. | |||
| //return 1 when split has been done. | |||
| //return -1 when error. | |||
| int CsgBsp::TestTriangleToTree(vec3 const &tri_v0, vec3 const &tri_v1, vec3 const &tri_v2, | |||
| //In order to easily build the actual vertices list afterward, this list stores each Vertices location and its source vertices & Alpha. | |||
| //<Point_Loc, Src_V0, Src_V1, Alpha> as { Point_Loc = Src_V0 + (Src_V1 - Src_V0) * Alpha; } | |||
| Array< vec3, int, int, float > &vert_list, | |||
| //This is the final triangle list : If Side_Status is LEAF_CURRENT, a new test will be done point by point. | |||
| //<{IN|OUT}side_status, v0, v1, v2> | |||
| Array< int, int, int, int > &tri_list) | |||
| { | |||
| //This list stores the current triangles to process. | |||
| //<Leaf_Id_List, v0, v1, v2, Should_Point_Test> | |||
| Array< Array< int >, int, int, int, int > tri_to_process; | |||
| //Tree is empty, ABORT ! | |||
| if (m_tree.Count() == 0) | |||
| return -1; | |||
| //Let's push the source vertices in here. | |||
| vert_list.Push(tri_v0, -1, -1, .0f); | |||
| vert_list.Push(tri_v1, -1, -1, .0f); | |||
| vert_list.Push(tri_v2, -1, -1, .0f); | |||
| //Let's push the triangle in here. | |||
| tri_to_process.Reserve(20); | |||
| tri_to_process.Push( Array< int >(), 0, 1, 2, 0); | |||
| tri_to_process.Last().m1.Push(0); | |||
| while (tri_to_process.Count()) | |||
| { | |||
| while (tri_to_process.Count()) | |||
| { | |||
| int leaf_idx = tri_to_process.Last().m1.Last(); | |||
| int t[3] = { tri_to_process.Last().m2, | |||
| tri_to_process.Last().m3, | |||
| tri_to_process.Last().m4 }; | |||
| vec3 v[3] = { vert_list[t[0]].m1, | |||
| vert_list[t[1]].m1, | |||
| vert_list[t[2]].m1 }; | |||
| int res_nb[3] = { 0, 0, 0 }; | |||
| int res_side[3] = { -1, -1, -1 }; | |||
| //Check where each point is located | |||
| for (int i = 0; i < 3; i++) | |||
| { | |||
| int result = TestPoint(leaf_idx, v[i]); | |||
| if (result != LEAF_CURRENT) | |||
| { | |||
| res_nb[result]++; | |||
| res_side[i] = result; | |||
| } | |||
| } | |||
| //Points are located on each sides, let's do the mumbo-jumbo | |||
| if (res_nb[LEAF_BACK] && res_nb[LEAF_FRONT]) | |||
| { | |||
| //there are two intersections, no more. | |||
| vec3 isec_v[2] = { vec3(.0f), vec3(.0f) }; | |||
| int isec_i[2] = { 0, 0 }; | |||
| int new_v_idx[2] = { 0, 0 }; | |||
| int isec_base = 0; | |||
| int isec_idx = 0; | |||
| int i = 0; | |||
| for (; i < m_tree[leaf_idx].m_tri_list.Count(); i++) | |||
| { | |||
| if (TriangleIsectTriangle(v[0], v[1], v[2], | |||
| m_tree[leaf_idx].m_tri_list[i].m2, m_tree[leaf_idx].m_tri_list[i].m3, m_tree[leaf_idx].m_tri_list[i].m4, | |||
| isec_v[0], isec_v[1])) | |||
| break; | |||
| } | |||
| //There was no triangle intersection, the complex case. | |||
| if (i == m_tree[leaf_idx].m_tri_list.Count()) | |||
| { | |||
| tri_to_process.Last().m1.Pop(); | |||
| //Register the triangle as needing to intersect with Front & back leaves. | |||
| if (m_tree[leaf_idx].m_leaves[LEAF_FRONT] != LEAF_CURRENT) | |||
| tri_to_process.Last().m1.Push(m_tree[leaf_idx].m_leaves[LEAF_FRONT]); | |||
| if (m_tree[leaf_idx].m_leaves[LEAF_BACK] != LEAF_CURRENT) | |||
| tri_to_process.Last().m1.Push(m_tree[leaf_idx].m_leaves[LEAF_BACK]); | |||
| //Mark the triangle as needing point by point test | |||
| tri_to_process.Last().m5 = 1; | |||
| } | |||
| //there was an intersection, so let's split the triangle. | |||
| else | |||
| { | |||
| //Get intersection on actual triangle sides. | |||
| if (RayIsectTriangleSide(v[0], v[1], v[2], | |||
| isec_v[0], isec_v[1], | |||
| isec_v[0], isec_i[0], isec_v[1], isec_i[1])) | |||
| { | |||
| { | |||
| for(int k = 0; k < 2; k++) | |||
| { | |||
| if (isec_base == isec_i[k]) | |||
| isec_base++; | |||
| #if 1 //Skip point creation if it's on the same location a one of the triangle. | |||
| bool skip_point = false; | |||
| int l = 0; | |||
| for(; l < 3; l++) | |||
| { | |||
| if (length(v[l] - isec_v[k]) < CSG_EPSILON) | |||
| { | |||
| skip_point = true; | |||
| new_v_idx[k] = t[l]; | |||
| break; | |||
| } | |||
| } | |||
| if (skip_point) | |||
| continue; | |||
| #endif | |||
| new_v_idx[k] = vert_list.Count(); | |||
| vec3 PmV0 = (isec_v[k] - vert_list[t[isec_i[k]]].m1); | |||
| vec3 V1mV0 = (vert_list[t[(isec_i[k] + 1) % 3]].m1 - vert_list[t[isec_i[k]]].m1); | |||
| float alpha = length(PmV0) / length(V1mV0); | |||
| vert_list.Push(isec_v[k], | |||
| t[isec_i[k]], t[(isec_i[k] + 1) % 3], | |||
| //Alpha = length((Point_Loc - Src_V0) / (Src_V1 - Src_V0)); | |||
| alpha); | |||
| } | |||
| int v_idx0 = (isec_base == 1)?(1):(0); | |||
| int v_idx1 = (isec_base == 1)?(0):(1); | |||
| //Leaf_type is the type for the triangle that is alone on its side. | |||
| int leaf_type = res_side[(isec_base + 2) % 3]; | |||
| int tri_to_remove = tri_to_process.Count() - 1; | |||
| #if 0 | |||
| if (m_tree[leaf_idx].m_leaves[leaf_type] == LEAF_CURRENT && tri_to_process.Last().m1.Last() == 1) | |||
| tri_list.Push(leaf_type, | |||
| t[(isec_base + 2) % 3], new_v_idx[v_idx1], new_v_idx[v_idx0]); | |||
| else | |||
| { | |||
| tri_to_process.Push(Array< int >(), t[(isec_base + 2) % 3], new_v_idx[v_idx1], new_v_idx[v_idx0], 0); | |||
| tri_to_process.Last().m1.Push(0); | |||
| } | |||
| if (m_tree[leaf_idx].m_leaves[1 - leaf_type] == LEAF_CURRENT && tri_to_process.Last().m1.Last() == 1) | |||
| { | |||
| tri_list.Push((tri_to_process.Last().m5)?(LEAF_CURRENT):(1 - leaf_type), | |||
| t[isec_base], new_v_idx[((isec_base + 1) % 3)], new_v_idx[v_idx0]); | |||
| tri_list.Push((tri_to_process.Last().m5)?(LEAF_CURRENT):(1 - leaf_type), | |||
| t[isec_base], new_v_idx[v_idx0], new_v_idx[v_idx1]); | |||
| } | |||
| else | |||
| { | |||
| tri_to_process.Push(Array< int >(), t[isec_base], t[((isec_base + 1) % 3)], new_v_idx[v_idx0], 0); | |||
| tri_to_process.Last().m1.Push(0); | |||
| tri_to_process.Push(Array< int >(), t[isec_base], new_v_idx[v_idx0], new_v_idx[v_idx1], 0); | |||
| tri_to_process.Last().m1.Push(0); | |||
| } | |||
| #else | |||
| int new_t[9] = { t[(isec_base + 2) % 3], new_v_idx[v_idx1], new_v_idx[v_idx0], | |||
| t[isec_base], t[((isec_base + 1) % 3)], new_v_idx[v_idx0], | |||
| t[isec_base], new_v_idx[v_idx0], new_v_idx[v_idx1] }; | |||
| int new_side[3] = { res_side[(isec_base + 2) % 3], | |||
| (res_side[isec_base] == LEAF_CURRENT)?(res_side[((isec_base + 1) % 3)]):(res_side[isec_base]), | |||
| res_side[isec_base] }; | |||
| //Error check : Skip the triangle where two points are on the same location. | |||
| //it fixes the problem of having an intersection with one of the isec-point being on one of the triangle vertices. | |||
| //(the problem being a very funny infinite loop) | |||
| for(int k = 0; k < 9; k += 3) | |||
| { | |||
| #if 1 //Error check | |||
| bool skip_tri = false; | |||
| for(int l = 0; l < 3; l++) | |||
| { | |||
| if (length(vert_list[new_t[k + l]].m1 - vert_list[new_t[k + (l + 1) % 3]].m1) < CSG_EPSILON) | |||
| { | |||
| skip_tri = true; | |||
| break; | |||
| } | |||
| } | |||
| if (skip_tri) | |||
| continue; | |||
| #endif | |||
| #if 0 //Send the newly created triangle back to the beginning | |||
| tri_to_process.Push(Array< int >(), new_t[k], new_t[k + 1], new_t[k + 2], 0); | |||
| tri_to_process.Last().m1.Push(0); | |||
| #else //Inherit parent tree | |||
| if (m_tree[leaf_idx].m_leaves[new_side[k / 3]] == LEAF_CURRENT && tri_to_process[tri_to_remove].m1.Count() == 1) | |||
| tri_list.Push(new_side[k / 3], new_t[k], new_t[k + 1], new_t[k + 2]); | |||
| else | |||
| { | |||
| tri_to_process.Push(Array< int >(), new_t[k], new_t[k + 1], new_t[k + 2], 0); | |||
| tri_to_process.Last().m1 = tri_to_process[tri_to_remove].m1; | |||
| if (m_tree[leaf_idx].m_leaves[new_side[k / 3]] == LEAF_CURRENT) | |||
| tri_to_process.Last().m1.Pop(); | |||
| else | |||
| tri_to_process.Last().m1.Last() = m_tree[leaf_idx].m_leaves[new_side[k / 3]]; | |||
| } | |||
| #endif | |||
| } | |||
| #endif | |||
| tri_to_process.Remove(tri_to_remove); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| //All points are on one side, transfer to the next leaf | |||
| else if (res_nb[LEAF_BACK] || res_nb[LEAF_FRONT]) | |||
| { | |||
| int new_leaf_type = ((res_nb[LEAF_FRONT])?(LEAF_FRONT):(LEAF_BACK)); | |||
| int new_leaf = m_tree[leaf_idx].m_leaves[new_leaf_type]; | |||
| //No leaf exist, we're at the end | |||
| if (new_leaf == LEAF_CURRENT) | |||
| { | |||
| //We still need to test other leaves. | |||
| if (tri_to_process.Last().m1.Count() > 1) | |||
| tri_to_process.Last().m1.Pop(); | |||
| else | |||
| { | |||
| tri_list.Push((tri_to_process.Last().m5)?(LEAF_CURRENT):(new_leaf_type), | |||
| tri_to_process.Last().m2, tri_to_process.Last().m3, tri_to_process.Last().m4); | |||
| tri_to_process.Pop(); | |||
| } | |||
| } | |||
| else | |||
| tri_to_process.Last().m1.Last() = new_leaf; | |||
| } | |||
| //All points are on the current leaf, add the tri_idx to the list of this leaf. | |||
| else | |||
| { | |||
| //TODO : Special case, handle coplanar cut. | |||
| tri_list.Push(LEAF_CURRENT, tri_to_process.Last().m2, tri_to_process.Last().m3, tri_to_process.Last().m4); | |||
| tri_to_process.Pop(); | |||
| } | |||
| } | |||
| //Now that we have all the split points, let's double-check the results | |||
| for (int i = 0; i < tri_list.Count(); i++) | |||
| { | |||
| #define TEST_MAX 4 | |||
| int t[3] = { tri_list[i].m2, | |||
| tri_list[i].m3, | |||
| tri_list[i].m4 }; | |||
| vec3 v[4] = { vert_list[t[0]].m1, | |||
| vert_list[t[1]].m1, | |||
| vert_list[t[2]].m1, | |||
| (vert_list[t[0]].m1 + | |||
| vert_list[t[1]].m1 + | |||
| vert_list[t[2]].m1) / 3.0f }; | |||
| int res_total = 0; | |||
| int res_nb[3] = { 0, 0, 0 }; | |||
| int res_Leaf[4] = { 0, 0, 0, 0 }; | |||
| int res_side[4] = { -1, -1, -1, -1 }; | |||
| while (res_total < TEST_MAX) | |||
| { | |||
| for (int k = 0; k < TEST_MAX; k++) | |||
| { | |||
| if (res_Leaf[k] != LEAF_CURRENT) | |||
| { | |||
| int result = TestPoint(res_Leaf[k], v[k]); | |||
| if (result != LEAF_CURRENT) | |||
| { | |||
| res_Leaf[k] = m_tree[res_Leaf[k]].m_leaves[result]; | |||
| res_side[k] = result; | |||
| if (res_Leaf[k] == LEAF_CURRENT) | |||
| { | |||
| res_total++; | |||
| res_nb[result]++; | |||
| } | |||
| } | |||
| else | |||
| { | |||
| res_Leaf[k] = LEAF_CURRENT; | |||
| res_side[k] = LEAF_CURRENT; | |||
| res_total++; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| int k = 0; | |||
| if (res_nb[LEAF_BACK] && res_nb[LEAF_FRONT]) | |||
| { | |||
| res_total = res_total; | |||
| tri_list[i].m1 = LEAF_BACK; | |||
| #if 0 | |||
| tri_to_process.Push( Array< int >(), tri_list[i].m2, tri_list[i].m3, tri_list[i].m4, 0); | |||
| tri_to_process.Last().m1.Push(0); | |||
| tri_list.Remove(i--); | |||
| break; | |||
| #endif | |||
| } | |||
| else | |||
| { | |||
| for (; k < TEST_MAX; k++) | |||
| { | |||
| if (res_side[k] != LEAF_CURRENT) | |||
| { | |||
| tri_list[i].m1 = res_side[k]; | |||
| break; | |||
| } | |||
| } | |||
| if (k == TEST_MAX) | |||
| tri_list[i].m1 = LEAF_FRONT; | |||
| } | |||
| } | |||
| } | |||
| if (tri_list.Count() == 1) | |||
| return 0; | |||
| return 1; | |||
| } | |||
| } /* namespace lol */ | |||
| @@ -0,0 +1,78 @@ | |||
| // | |||
| // Lol Engine | |||
| // | |||
| // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net> | |||
| // (c) 2010-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com> | |||
| // This program is free software; you can redistribute it and/or | |||
| // modify it under the terms of the Do What The Fuck You Want To | |||
| // Public License, Version 2, as published by Sam Hocevar. See | |||
| // http://www.wtfpl.net/ for more details. | |||
| // | |||
| // | |||
| // The EasyMesh class | |||
| // ------------------ | |||
| // | |||
| #if !defined __CSGBSP_CSGBSP_H__ | |||
| #define __CSGBSP_CSGBSP_H__ | |||
| namespace lol | |||
| { | |||
| #define LEAF_ABOVE 2 | |||
| #define LEAF_FRONT 1 | |||
| #define LEAF_BACK 0 | |||
| #define LEAF_CURRENT -1 | |||
| //Naïve bsp for the poor people | |||
| class CsgBspLeaf | |||
| { | |||
| friend class CsgBsp; | |||
| public: | |||
| CsgBspLeaf(vec3 origin, vec3 normal, int above_idx) | |||
| { | |||
| m_origin = origin; | |||
| m_normal = normal; | |||
| m_leaves[LEAF_ABOVE] = above_idx; | |||
| m_leaves[LEAF_FRONT] = -1; | |||
| m_leaves[LEAF_BACK] = -1; | |||
| } | |||
| private: | |||
| vec3 m_origin; | |||
| vec3 m_normal; | |||
| Array< int, vec3, vec3, vec3 > m_tri_list; | |||
| ivec3 m_leaves; | |||
| }; | |||
| //Naïve bsp for the poor people | |||
| class CsgBsp | |||
| { | |||
| public: | |||
| void AddTriangleToTree(int const &tri_idx, vec3 const &tri_v0, vec3 const &tri_v1, vec3 const &tri_v2); | |||
| //return 0 when no split has been done. | |||
| //return 1 when split has been done. | |||
| //return -1 when error. | |||
| int TestTriangleToTree(vec3 const &tri_v0, vec3 const &tri_v1, vec3 const &tri_v2, | |||
| //In order to easily build the actual vertices list afterward, this list stores each Vertices location and its source vertices & Alpha. | |||
| //<Point_Loc, Src_V0, Src_V1, Alpha> as { Point_Loc = Src_V0 + (Src_V1 - Src_V0) * Alpha; } | |||
| Array< vec3, int, int, float > &vert_list, | |||
| //This is the final triangle list : If Side_Status is LEAF_CURRENT, a new test will be done point by point. | |||
| //<{IN|OUT}side_status, v0, v1, v2> | |||
| Array< int, int, int, int > &tri_list); | |||
| private: | |||
| int AddLeaf(int leaf_type, vec3 origin, vec3 normal, int above_idx); | |||
| int TestPoint(int leaf_idx, vec3 point); | |||
| Array<CsgBspLeaf> m_tree; | |||
| }; | |||
| } /* namespace lol */ | |||
| #endif /* __CSGBSP_CSGBSP_H__ */ | |||
| @@ -1,9 +1,9 @@ | |||
| // | |||
| // Lol Engine | |||
| // | |||
| // Copyright: (c) 2010-2012 Sam Hocevar <sam@hocevar.net> | |||
| // (c) 2009-2012 Cédric Lecacheur <jordx@free.fr> | |||
| // (c) 2009-2012 Benjamin Huet <huet.benjamin@gmail.com> | |||
| // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net> | |||
| // (c) 2009-2013 Cédric Lecacheur <jordx@free.fr> | |||
| // (c) 2009-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com> | |||
| // This program is free software; you can redistribute it and/or | |||
| // modify it under the terms of the Do What The Fuck You Want To | |||
| // Public License, Version 2, as published by Sam Hocevar. See | |||
| @@ -1,9 +1,9 @@ | |||
| // | |||
| // Lol Engine | |||
| // | |||
| // Copyright: (c) 2010-2012 Sam Hocevar <sam@hocevar.net> | |||
| // (c) 2009-2012 Cédric Lecacheur <jordx@free.fr> | |||
| // (c) 2009-2012 Benjamin Huet <huet.benjamin@gmail.com> | |||
| // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net> | |||
| // (c) 2009-2013 Cédric Lecacheur <jordx@free.fr> | |||
| // (c) 2009-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com> | |||
| // This program is free software; you can redistribute it and/or | |||
| // modify it under the terms of the Do What The Fuck You Want To | |||
| // Public License, Version 2, as published by Sam Hocevar. See | |||
| @@ -2,9 +2,9 @@ | |||
| // | |||
| // Lol Engine | |||
| // | |||
| // Copyright: (c) 2010-2012 Sam Hocevar <sam@hocevar.net> | |||
| // (c) 2009-2012 Cédric Lecacheur <jordx@free.fr> | |||
| // (c) 2009-2012 Benjamin Huet <huet.benjamin@gmail.com> | |||
| // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net> | |||
| // (c) 2009-2013 Cédric Lecacheur <jordx@free.fr> | |||
| // (c) 2009-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com> | |||
| // This program is free software; you can redistribute it and/or | |||
| // modify it under the terms of the Do What The Fuck You Want To | |||
| // Public License, Version 2, as published by Sam Hocevar. See | |||
| @@ -48,6 +48,7 @@ | |||
| %token T_TRANSLATEY T_ROTATEY T_TAPERY T_SCALEY T_MIRRORY | |||
| %token T_TRANSLATEZ T_ROTATEZ T_TAPERZ T_SCALEZ T_MIRRORZ | |||
| %token T_TRANSLATE T_SCALE T_TOGGLESCALEWINDING | |||
| %token T_CSGUNION T_CSGSUBSTRACT T_CSGAND T_CSGXOR | |||
| %token T_CHAMFER | |||
| %token T_CYLINDER T_BOX T_SMOOTHCHAMFBOX T_FLATCHAMFBOX T_SPHERE T_CAPSULE | |||
| @@ -116,25 +117,29 @@ color_command: | |||
| ; | |||
| transform_command: | |||
| T_CHAMFER args1 { mc.m_mesh.Chamfer($2.f0); } | |||
| | T_TRANSLATEX args1 { mc.m_mesh.Translate(vec3($2.f0, 0, 0)); } | |||
| | T_TRANSLATEY args1 { mc.m_mesh.Translate(vec3(0, $2.f0, 0)); } | |||
| | T_TRANSLATEZ args1 { mc.m_mesh.Translate(vec3(0, 0, $2.f0)); } | |||
| | T_TRANSLATE args3 { mc.m_mesh.Translate(vec3($2.f0, $2.f1, $2.f2)); } | |||
| | T_ROTATEX args1 { mc.m_mesh.RotateX($2.f0); } | |||
| | T_ROTATEY args1 { mc.m_mesh.RotateY($2.f0); } | |||
| | T_ROTATEZ args1 { mc.m_mesh.RotateZ($2.f0); } | |||
| | T_TAPERX args3 { mc.m_mesh.TaperX($2.f0, $2.f1, $2.f2); } | |||
| | T_TAPERY args3 { mc.m_mesh.TaperY($2.f0, $2.f1, $2.f2); } | |||
| | T_TAPERZ args3 { mc.m_mesh.TaperZ($2.f0, $2.f1, $2.f2); } | |||
| | T_SCALEX args1 { mc.m_mesh.Scale(vec3($2.f0, 1.0, 1.0)); } | |||
| | T_SCALEY args1 { mc.m_mesh.Scale(vec3(1.0, $2.f0, 1.0)); } | |||
| | T_SCALEZ args1 { mc.m_mesh.Scale(vec3(1.0, 1.0, $2.f0)); } | |||
| | T_SCALE args3 { mc.m_mesh.Scale(vec3($2.f0, $2.f1, $2.f2)); } | |||
| | T_MIRRORX { mc.m_mesh.MirrorX(); } | |||
| | T_MIRRORY { mc.m_mesh.MirrorY(); } | |||
| | T_MIRRORZ { mc.m_mesh.MirrorZ(); } | |||
| | T_TOGGLESCALEWINDING { mc.m_mesh.ToggleScaleWinding(); } | |||
| T_CHAMFER args1 { mc.m_mesh.Chamfer($2.f0); } | |||
| | T_TRANSLATEX args1 { mc.m_mesh.Translate(vec3($2.f0, 0, 0)); } | |||
| | T_TRANSLATEY args1 { mc.m_mesh.Translate(vec3(0, $2.f0, 0)); } | |||
| | T_TRANSLATEZ args1 { mc.m_mesh.Translate(vec3(0, 0, $2.f0)); } | |||
| | T_TRANSLATE args3 { mc.m_mesh.Translate(vec3($2.f0, $2.f1, $2.f2)); } | |||
| | T_ROTATEX args1 { mc.m_mesh.RotateX($2.f0); } | |||
| | T_ROTATEY args1 { mc.m_mesh.RotateY($2.f0); } | |||
| | T_ROTATEZ args1 { mc.m_mesh.RotateZ($2.f0); } | |||
| | T_TAPERX args3 { mc.m_mesh.TaperX($2.f0, $2.f1, $2.f2); } | |||
| | T_TAPERY args3 { mc.m_mesh.TaperY($2.f0, $2.f1, $2.f2); } | |||
| | T_TAPERZ args3 { mc.m_mesh.TaperZ($2.f0, $2.f1, $2.f2); } | |||
| | T_SCALEX args1 { mc.m_mesh.Scale(vec3($2.f0, 1.0, 1.0)); } | |||
| | T_SCALEY args1 { mc.m_mesh.Scale(vec3(1.0, $2.f0, 1.0)); } | |||
| | T_SCALEZ args1 { mc.m_mesh.Scale(vec3(1.0, 1.0, $2.f0)); } | |||
| | T_SCALE args3 { mc.m_mesh.Scale(vec3($2.f0, $2.f1, $2.f2)); } | |||
| | T_MIRRORX { mc.m_mesh.MirrorX(); } | |||
| | T_MIRRORY { mc.m_mesh.MirrorY(); } | |||
| | T_MIRRORZ { mc.m_mesh.MirrorZ(); } | |||
| | T_TOGGLESCALEWINDING { mc.m_mesh.ToggleScaleWinding(); } | |||
| | T_CSGUNION { mc.m_mesh.CsgUnion(); } | |||
| | T_CSGSUBSTRACT { mc.m_mesh.CsgSubstract(); } | |||
| | T_CSGAND { mc.m_mesh.CsgAnd(); } | |||
| | T_CSGXOR { mc.m_mesh.CsgXor(); } | |||
| ; | |||
| primitive_command: | |||
| @@ -2,9 +2,9 @@ | |||
| // | |||
| // Lol Engine | |||
| // | |||
| // Copyright: (c) 2010-2012 Sam Hocevar <sam@hocevar.net> | |||
| // (c) 2009-2012 Cédric Lecacheur <jordx@free.fr> | |||
| // (c) 2009-2012 Benjamin Huet <huet.benjamin@gmail.com> | |||
| // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net> | |||
| // (c) 2009-2013 Cédric Lecacheur <jordx@free.fr> | |||
| // (c) 2009-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com> | |||
| // This program is free software; you can redistribute it and/or | |||
| // modify it under the terms of the Do What The Fuck You Want To | |||
| // Public License, Version 2, as published by Sam Hocevar. See | |||
| @@ -71,6 +71,11 @@ mx { return token::T_MIRRORX; } | |||
| my { return token::T_MIRRORY; } | |||
| mz { return token::T_MIRRORZ; } | |||
| csgu { return token::T_CSGUNION; } | |||
| csgs { return token::T_CSGSUBSTRACT; } | |||
| csga { return token::T_CSGAND; } | |||
| csgx { return token::T_CSGXOR; } | |||
| ab { return token::T_BOX; } | |||
| ac { return token::T_CYLINDER; } | |||
| acap { return token::T_CAPSULE; } | |||
| @@ -1,9 +1,9 @@ | |||
| // | |||
| // Lol Engine | |||
| // | |||
| // Copyright: (c) 2010-2012 Sam Hocevar <sam@hocevar.net> | |||
| // (c) 2009-2012 Cédric Lecacheur <jordx@free.fr> | |||
| // (c) 2009-2012 Benjamin Huet <huet.benjamin@gmail.com> | |||
| // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net> | |||
| // (c) 2009-2013 Cédric Lecacheur <jordx@free.fr> | |||
| // (c) 2009-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com> | |||
| // This program is free software; you can redistribute it and/or | |||
| // modify it under the terms of the Do What The Fuck You Want To | |||
| // Public License, Version 2, as published by Sam Hocevar. See | |||
| @@ -75,7 +75,7 @@ void EasyMesh::MeshConvert(Shader* provided_shader) | |||
| m_gpu.modelview = m_gpu.shader->GetUniformLocation("in_ModelView"); | |||
| m_gpu.view = m_gpu.shader->GetUniformLocation("in_View"); | |||
| m_gpu.invview = m_gpu.shader->GetUniformLocation("in_Inv_View"); | |||
| m_gpu.invview = m_gpu.shader->GetUniformLocation("in_Inv_View"); | |||
| m_gpu.proj = m_gpu.shader->GetUniformLocation("in_Proj"); | |||
| m_gpu.normalmat = m_gpu.shader->GetUniformLocation("in_NormalMat"); | |||
| m_gpu.damage = m_gpu.shader->GetUniformLocation("in_Damage"); | |||
| @@ -141,6 +141,403 @@ void EasyMesh::Render(mat4 const &model, float damage) | |||
| m_gpu.vdecl->Unbind(); | |||
| } | |||
| //------------------- | |||
| // "Collisions" functions | |||
| //------------------- | |||
| #define VX_ALONE -2 | |||
| #define VX_MASTER -1 | |||
| //helpers func to retrieve a vertex. | |||
| int FindVertexInDict(int search_idx, Array< int, int > const &vertex_dict) | |||
| { | |||
| //Resolve current vertex idx in the dictionnary (if exist) | |||
| for (int j = 0; j < vertex_dict.Count(); j++) | |||
| if (vertex_dict[j].m1 == search_idx) | |||
| return j; | |||
| return -1; | |||
| } | |||
| //helpers func to retrieve a triangle. | |||
| int FindTriangleInDict(int search_idx, Array< int, Array< vec3, vec3, vec3 > > const &triangle_isec) | |||
| { | |||
| //Resolve current vertex idx in the dictionnary (if exist) | |||
| for (int j = 0; j < triangle_isec.Count(); j++) | |||
| if (triangle_isec[j].m1 == search_idx) | |||
| return j; | |||
| return -1; | |||
| } | |||
| //Will update the given list with all the vertices on the same spot. | |||
| void EasyMesh::UpdateVertexDict(Array< int, int > &vertex_dict) | |||
| { | |||
| //First, build the vertex Dictionnary | |||
| for (int i = 0; i < m_vert.Count(); i++) | |||
| { | |||
| int CurIdx = FindVertexInDict(i, vertex_dict); | |||
| //go through all vertices and do the match-up. | |||
| if (CurIdx == -1) | |||
| { | |||
| for (int j = i + 1; j < m_vert.Count(); j++) | |||
| { | |||
| if (sqlength(m_vert[i].m1 - m_vert[j].m1) < CSG_EPSILON) | |||
| { | |||
| if (CurIdx == -1) | |||
| { | |||
| CurIdx = vertex_dict.Count(); | |||
| vertex_dict.Push(i, VX_MASTER); | |||
| } | |||
| vertex_dict.Push(j, CurIdx); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| void EasyMesh::MeshCsg(int csg_operation) | |||
| { | |||
| //A vertex dictionnary for vertices on the same spot. | |||
| Array< int, int > vertex_dict; | |||
| //This list keeps track of the triangle that will need deletion at the end. | |||
| Array< int > triangle_to_kill; | |||
| //Listing for each triangle of the vectors intersecting it. <tri_Id, <Point0, Point1, tri_isec_Normal>> | |||
| Array< int, Array< vec3, vec3, vec3 > > triangle_isec; | |||
| //keep a track of the intersection point on the triangle. <pos, side_id> | |||
| Array< vec3, int > triangle_vertex; | |||
| for (int k = 0; k < 10; k++) | |||
| triangle_vertex.Push(vec3(.0f), 0); | |||
| //bsp infos | |||
| CsgBsp mesh_bsp_0; | |||
| CsgBsp mesh_bsp_1; | |||
| //BSP BUILD : We use the brace logic, csg should be used as : "[ exp .... [exp .... csg]]" | |||
| int cursor_start = (m_cursors.Count() < 2)?(0):(m_cursors[(m_cursors.Count() - 2)].m2); | |||
| for (int mesh_id = 0; mesh_id < 2; mesh_id++) | |||
| { | |||
| int start_point = (mesh_id == 0)?(cursor_start):(m_cursors.Last().m2); | |||
| int end_point = (mesh_id == 0)?(m_cursors.Last().m2):(m_indices.Count()); | |||
| CsgBsp &mesh_bsp = (mesh_id == 0)?(mesh_bsp_0):(mesh_bsp_1); | |||
| for (int i = start_point; i < end_point; i += 3) | |||
| mesh_bsp.AddTriangleToTree(i, m_vert[m_indices[i]].m1, m_vert[m_indices[i + 1]].m1, m_vert[m_indices[i + 2]].m1); | |||
| } | |||
| //BSP Useage : let's crunch all triangles on the correct BSP | |||
| int indices_count = m_indices.Count(); | |||
| for (int mesh_id = 0; mesh_id < 2; mesh_id++) | |||
| { | |||
| int start_point = (mesh_id == 0)?(cursor_start):(m_cursors.Last().m2); | |||
| int end_point = (mesh_id == 0)?(m_cursors.Last().m2):(indices_count); | |||
| CsgBsp &mesh_bsp = (mesh_id == 0)?(mesh_bsp_1):(mesh_bsp_0); | |||
| Array< vec3, int, int, float > vert_list; | |||
| Array< int, int, int, int > tri_list; | |||
| vec3 n0(.0f); vec3 n1(.0f); | |||
| vec4 c0(.0f); vec4 c1(.0f); | |||
| //Reserve some memory | |||
| vert_list.Reserve(3); | |||
| tri_list.Reserve(3); | |||
| for (int i = start_point; i < end_point; i += 3) | |||
| { | |||
| int Result = mesh_bsp.TestTriangleToTree(m_vert[m_indices[i]].m1, m_vert[m_indices[i + 1]].m1, m_vert[m_indices[i + 2]].m1, vert_list, tri_list); | |||
| int tri_base_idx = m_indices.Count(); | |||
| //one split has been done, we need to had the new vertices & the new triangles. | |||
| if (Result == 1) | |||
| { | |||
| triangle_to_kill.Push(i); | |||
| #if 1 | |||
| int base_idx = m_vert.Count(); | |||
| for (int k = 3; k < vert_list.Count(); k++) | |||
| { | |||
| int P0 = (vert_list[k].m2 < 3)?(m_indices[i + vert_list[k].m2]):(base_idx + vert_list[k].m2 - 3); | |||
| int P1 = (vert_list[k].m3 < 3)?(m_indices[i + vert_list[k].m3]):(base_idx + vert_list[k].m3 - 3); | |||
| AddVertex(vert_list[k].m1); | |||
| //Normal : bad calculations there. | |||
| n0 = m_vert[P0].m2; | |||
| n1 = m_vert[P1].m2; | |||
| SetCurVertNormal(normalize(n0 + (n1 - n0) * vert_list[k].m4)); | |||
| #if 1 | |||
| //Color | |||
| c0 = m_vert[P0].m3; | |||
| c1 = m_vert[P1].m3; | |||
| vec4 res = c0 + ((c1 - c0) * vert_list[k].m4); | |||
| SetCurVertColor(res); | |||
| #else | |||
| if (mesh_id == 0) | |||
| SetCurVertColor(vec4(1.0f, .0f, .0f, 1.0f)); | |||
| else | |||
| SetCurVertColor(vec4(.0f, 1.0f, 1.0f, 1.0f)); | |||
| #endif | |||
| } | |||
| for (int k = 0; k < tri_list.Count(); k++) | |||
| { | |||
| int P0 = (tri_list[k].m2 < 3)?(m_indices[i + tri_list[k].m2]):(base_idx + (tri_list[k].m2 - 3)); | |||
| int P1 = (tri_list[k].m3 < 3)?(m_indices[i + tri_list[k].m3]):(base_idx + (tri_list[k].m3 - 3)); | |||
| int P2 = (tri_list[k].m4 < 3)?(m_indices[i + tri_list[k].m4]):(base_idx + (tri_list[k].m4 - 3)); | |||
| AppendTriangle(P0, P1, P2, 0); | |||
| } | |||
| #endif | |||
| } | |||
| #if 1 | |||
| //Main case | |||
| if (Result >= 0) | |||
| { | |||
| for (int k = 0; k < tri_list.Count(); k++) | |||
| { | |||
| int tri_idx = ((tri_list.Count() == 1)?(i):(tri_base_idx + k * 3)); | |||
| //Triangle Kill Test | |||
| if (//csgu : CSGUnion() -> m0_Outside + m1_Outside | |||
| (csg_operation == CSG_UNION && tri_list[k].m1 == LEAF_BACK) || | |||
| //csgs : CSGSubstract() -> m0_Outside + m1_Inside-inverted | |||
| (csg_operation == CSG_SUBSTRACT && | |||
| ((mesh_id == 0 && tri_list[k].m1 == LEAF_BACK) || | |||
| (mesh_id == 1 && tri_list[k].m1 == LEAF_FRONT))) || | |||
| //csga : CSGAnd() -> Inside + Inside | |||
| (csg_operation == CSG_AND && tri_list[k].m1 == LEAF_FRONT)) | |||
| { | |||
| triangle_to_kill.Push(tri_idx); | |||
| } | |||
| //Triangle Invert Test | |||
| if (//csgs : CSGSubstract() -> m0_Outside + m1_Inside-inverted | |||
| (csg_operation == CSG_SUBSTRACT && mesh_id == 1 && tri_list[k].m1 == LEAF_BACK) || | |||
| //csgx : CSGXor() -> Outside/Inside-inverted + Outside/Inside-inverted | |||
| (csg_operation == CSG_XOR && tri_list[k].m1 == LEAF_BACK)) | |||
| { | |||
| //a Xor means we will share vertices with the outside, so duplicate the vertices. | |||
| //TODO : This operation disconnect all triangle, in some cases, not a good thing. | |||
| if (csg_operation == CSG_XOR) | |||
| { | |||
| for (int l = 0; l < 3; l++) | |||
| { | |||
| AddDuplicateVertex(m_indices[tri_idx + l]); | |||
| m_indices[tri_idx + l] = m_vert.Count() - 1; | |||
| } | |||
| } | |||
| m_indices[tri_idx + 1] += m_indices[tri_idx + 2]; | |||
| m_indices[tri_idx + 2] = m_indices[tri_idx + 1] - m_indices[tri_idx + 2]; | |||
| m_indices[tri_idx + 1] = m_indices[tri_idx + 1] - m_indices[tri_idx + 2]; | |||
| ComputeNormals(tri_idx, 3); | |||
| } | |||
| } | |||
| } | |||
| #endif | |||
| vert_list.Empty(); | |||
| tri_list.Empty(); | |||
| } | |||
| } | |||
| for (int i = 0; i < m_vert.Count(); i++) | |||
| if (length(m_vert[i].m2) < 1.0f) | |||
| i = i; | |||
| int dir = 1; | |||
| for (int i = 0; i >= 0 && i < triangle_to_kill.Count() - 1; i += dir) | |||
| { | |||
| if (triangle_to_kill[i] < triangle_to_kill[i + 1] && dir < 0) | |||
| dir = 1; | |||
| if (triangle_to_kill[i] == triangle_to_kill[i + 1]) | |||
| { | |||
| triangle_to_kill.Remove(i); | |||
| dir = -1; | |||
| } | |||
| if (triangle_to_kill[i] > triangle_to_kill[i + 1]) | |||
| { | |||
| triangle_to_kill[i] += triangle_to_kill[i + 1]; | |||
| triangle_to_kill[i + 1] = triangle_to_kill[i] - triangle_to_kill[i + 1]; | |||
| triangle_to_kill[i] = triangle_to_kill[i] - triangle_to_kill[i + 1]; | |||
| dir = -1; | |||
| } | |||
| if (i == 0 && dir == -1) | |||
| dir = 1; | |||
| } | |||
| for (int i = triangle_to_kill.Count() - 1; i >= 0; i--) | |||
| m_indices.Remove(triangle_to_kill[i], 3); | |||
| m_cursors.Last().m1 = m_vert.Count(); | |||
| m_cursors.Last().m2 = m_indices.Count(); | |||
| #if 0 | |||
| UpdateVertexDict(vertex_dict); | |||
| for (int t0 = 0; t0 < m_indices.Count(); t0 += 3) | |||
| { | |||
| for (int t1 = t0 + 3; t1 < m_indices.Count(); t1 += 3) | |||
| { | |||
| int CommonVertices = 0; | |||
| //Search for common vertices, if > 1 the two triangle share a side, so no split is required. | |||
| for (int k = 0; k < 3; k++) | |||
| { | |||
| int ref_master = FindVertexInDict(m_indices[t0 + k], vertex_dict); | |||
| if (ref_master != -1) | |||
| { | |||
| if (vertex_dict[ref_master].m2 != VX_MASTER) | |||
| ref_master = vertex_dict[ref_master].m2; | |||
| for (int l = 0; l < 3; l++) | |||
| { | |||
| int test_master = FindVertexInDict(m_indices[t1 + l], vertex_dict); | |||
| if (test_master != -1) | |||
| { | |||
| if (vertex_dict[test_master].m2 != VX_MASTER) | |||
| test_master = vertex_dict[test_master].m2; | |||
| if (test_master == ref_master) | |||
| { | |||
| CommonVertices++; | |||
| break; | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| if (CommonVertices < 2) | |||
| { | |||
| vec3 iP0, iP1; | |||
| //Build the triangle intersection list | |||
| if (TriangleIsectTriangle(m_vert[m_indices[t0]].m1, m_vert[m_indices[t0 + 1]].m1, m_vert[m_indices[t0 + 2]].m1, | |||
| m_vert[m_indices[t1]].m1, m_vert[m_indices[t1 + 1]].m1, m_vert[m_indices[t1 + 2]].m1, | |||
| iP0, iP1)) | |||
| { | |||
| int CurIdx = FindTriangleInDict(t0, triangle_isec); | |||
| if (CurIdx == -1) | |||
| { | |||
| CurIdx = triangle_isec.Count(); | |||
| triangle_isec.Push(t0, Array<vec3, vec3, vec3>()); | |||
| } | |||
| triangle_isec[CurIdx].m2.Push(iP0, iP1, vec3(.0f)); | |||
| CurIdx = FindTriangleInDict(t1, triangle_isec); | |||
| if (CurIdx == -1) | |||
| { | |||
| CurIdx = triangle_isec.Count(); | |||
| triangle_isec.Push(t1, Array<vec3, vec3, vec3>()); | |||
| } | |||
| triangle_isec[CurIdx].m2.Push(iP0, iP1, vec3(.0f)); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| /* seems to be counter-productive in some rare cases. */ | |||
| /* | |||
| //Every intersection has been found, let's remove those that exist twice. | |||
| for(int i = 0; i < triangle_isec.Count(); i++) | |||
| { | |||
| for(int j = 0; j < triangle_isec[i].m2.Count(); j++) | |||
| { | |||
| for(int k = j + 1; k < triangle_isec[i].m2.Count(); k++) | |||
| { | |||
| //if the two Dir-vector are parallel & the fist Dir-vector is parallel to the (P0, P1)-vector, this is the same intersection, so kill it. | |||
| if (abs(dot(normalize(triangle_isec[i].m2[j].m2 - triangle_isec[i].m2[j].m1), | |||
| normalize(triangle_isec[i].m2[k].m2 - triangle_isec[i].m2[k].m1))) | |||
| >= 1.0 && | |||
| abs(dot(normalize(triangle_isec[i].m2[j].m2 - triangle_isec[i].m2[j].m1), | |||
| normalize(triangle_isec[i].m2[k].m1 - triangle_isec[i].m2[j].m1))) | |||
| >= 1.0 ) | |||
| triangle_isec[i].m2.Remove(k--); | |||
| } | |||
| } | |||
| } | |||
| */ | |||
| //Now, the triangle intersection tab should be nice and cosy, so we can start actually cutting some triangles. | |||
| vec3 isecV[2] = { vec3(.0f), vec3(.0f) }; | |||
| int isecI[2] = { -1, -1 }; | |||
| int v_idx0 = 0; int v_idx1 = 0; | |||
| int new_v_idx[2] = { 0, 0 }; | |||
| vec3 n0(.0f); vec3 n1(.0f); | |||
| vec4 c0(.0f); vec4 c1(.0f); | |||
| for(int i = 0; i < triangle_isec.Count(); i++) | |||
| { | |||
| int tri_idx = triangle_isec[i].m1; | |||
| for(int j = 0; j < triangle_isec[i].m2.Count(); j++) | |||
| { | |||
| //Get intersection on actual triangle sides. | |||
| if (RayIsectTriangleSide(m_vert[m_indices[tri_idx]].m1, m_vert[m_indices[tri_idx + 1]].m1, m_vert[m_indices[tri_idx + 2]].m1, | |||
| triangle_isec[i].m2[j].m1, triangle_isec[i].m2[j].m2, | |||
| isecV[0], isecI[0], isecV[1], isecI[1])) | |||
| { | |||
| //Check if the found intersections point are in the triangle. If not, ignore. | |||
| //Cases are : | |||
| // 1) at least one dot is negative (one point in the triangle). | |||
| // 2) the two dot are positive but the intersection point are on all parts of the triangle, and therefore negative. | |||
| //If one of the point is on one side, some calculations tweak are needed. | |||
| //If the two points are on the triangle sides, just go with it. | |||
| bool should_proceed_with_cutting = true; | |||
| //find out if points are on one of the side | |||
| int p0_tri_idx = ((sqlength(triangle_isec[i].m2[j].m1 - isecV[0]) < CSG_EPSILON)?(0):( | |||
| (sqlength(triangle_isec[i].m2[j].m1 - isecV[1]) < CSG_EPSILON)?(1):(-1))); | |||
| int p1_tri_idx = ((sqlength(triangle_isec[i].m2[j].m2 - isecV[0]) < CSG_EPSILON)?(0):( | |||
| (sqlength(triangle_isec[i].m2[j].m2 - isecV[1]) < CSG_EPSILON)?(1):(-1))); | |||
| if (p0_tri_idx < 0 || p1_tri_idx < 0) | |||
| { | |||
| float dot0 = (p0_tri_idx >= 0)?(1.0f):(dot(triangle_isec[i].m2[j].m1 - isecV[0], | |||
| triangle_isec[i].m2[j].m1 - isecV[1])); | |||
| float dot1 = (p1_tri_idx >= 0)?(1.0f):(dot(triangle_isec[i].m2[j].m2 - isecV[0], | |||
| triangle_isec[i].m2[j].m2 - isecV[1])); | |||
| float dot2 = dot(triangle_isec[i].m2[j].m1 - isecV[(p0_tri_idx == -1)?(0):(1 - p0_tri_idx)], | |||
| triangle_isec[i].m2[j].m2 - isecV[(p1_tri_idx == -1)?(0):(1 - p1_tri_idx)]); | |||
| should_proceed_with_cutting = (((dot0 < .0f) || dot1 < .0f) || (dot0 > .0f && dot1 > .0f && dot2 < .0f)); | |||
| } | |||
| if (should_proceed_with_cutting) | |||
| { | |||
| //Add the new vertices | |||
| int b_idx = 0; | |||
| for(int k = 0; k < 2; k++) | |||
| { | |||
| if (b_idx == isecI[k]) | |||
| b_idx++; | |||
| new_v_idx[k] = m_vert.Count(); | |||
| AddVertex(isecV[k]); | |||
| //bad calculations of normal there. | |||
| n0 = m_vert[m_indices[tri_idx + isecI[k]]].m2; | |||
| n1 = m_vert[m_indices[tri_idx + (isecI[k] + 1) % 3]].m2; | |||
| SetCurVertNormal(normalize((n0 + n1) * .5f)); | |||
| //color | |||
| #if 0 | |||
| c0 = m_vert[m_indices[tri_idx + isecI[k]]].m3; | |||
| c1 = m_vert[m_indices[tri_idx + (isecI[k] + 1) % 3]].m3; | |||
| SetCurVertColor((c0 + c1) * .5f); | |||
| #else | |||
| SetCurVertColor(vec4(1.0f, 0.0f, 0.0f, 1.0f)); | |||
| #endif | |||
| } | |||
| //small trick, b_idx is the side index that has no intersection. | |||
| v_idx0 = (b_idx == 1)?(1):(0); | |||
| v_idx1 = (b_idx == 1)?(0):(1); | |||
| //Add the new triangles | |||
| AppendTriangle(m_indices[tri_idx + b_idx], new_v_idx[v_idx0], new_v_idx[v_idx1], 0); | |||
| AppendTriangle(m_indices[tri_idx + ((b_idx + 2) % 3)], new_v_idx[v_idx1], new_v_idx[v_idx0], 0); | |||
| //Replace the current triangle by on of the new one, instead of erasing it. | |||
| m_indices[tri_idx + ((b_idx + 2) % 3)] = new_v_idx[v_idx0]; | |||
| if (j + 1 < triangle_isec[i].m2.Count()) | |||
| { | |||
| triangle_isec[i].m2.Remove(j--); | |||
| //add the two new triangle to the checklist. | |||
| triangle_isec.Push(m_indices.Count() - 6, triangle_isec[i].m2); | |||
| triangle_isec.Push(m_indices.Count() - 3, triangle_isec[i].m2); | |||
| } | |||
| } | |||
| } | |||
| } | |||
| } | |||
| #endif | |||
| //DONE for the splitting ! | |||
| } | |||
| //------------------- | |||
| void EasyMesh::ToggleScaleWinding() | |||
| { | |||
| m_ignore_winding_on_scale = !m_ignore_winding_on_scale; | |||
| @@ -434,7 +831,7 @@ void EasyMesh::AppendCapsule(int ndivisions, float h, float r) | |||
| /* Fill in the icosahedron vertices, rotating them so that there | |||
| * is a vertex at [0 1 0] and [0 -1 0] after normalisation. */ | |||
| float phi = 0.5f + 0.5f * sqrt(5.f); | |||
| mat3 mat = mat3::rotate(asin(1.f / sqrt(2.f + phi)) * (180.f / M_PI), | |||
| mat3 mat = mat3::rotate(asin(1.f / sqrt(2.f + phi)) * (180.f / (float)M_PI), | |||
| vec3(0.f, 0.f, 1.f)); | |||
| for (int i = 0; i < 4; i++) | |||
| { | |||
| @@ -538,12 +935,12 @@ void EasyMesh::AppendTorus(int ndivisions, float r1, float r2) | |||
| { | |||
| int i2 = (i + di) % nidiv; | |||
| int j2 = (j + dj) % njdiv; | |||
| float x = 0.5f * (r1 + r2) + 0.5 * (r2 - r1) * lol::cos(2.0 * M_PI * i2 / nidiv); | |||
| float y = 0.5f * (r2 - r1) * lol::sin(2.0 * M_PI * i2 / nidiv); | |||
| float x = 0.5f * (r1 + r2) + 0.5f * (r2 - r1) * (float)lol::cos(2.0 * M_PI * i2 / nidiv); | |||
| float y = 0.5f * (r2 - r1) * (float)lol::sin(2.0 * M_PI * i2 / nidiv); | |||
| float z = 0.0f; | |||
| float ca = lol::cos(2.0 * M_PI * j2 / njdiv); | |||
| float sa = lol::sin(2.0 * M_PI * j2 / njdiv); | |||
| float ca = (float)lol::cos(2.0 * M_PI * j2 / njdiv); | |||
| float sa = (float)lol::sin(2.0 * M_PI * j2 / njdiv); | |||
| float x2 = x * ca - z * sa; | |||
| float z2 = z * ca + x * sa; | |||
| @@ -1,9 +1,9 @@ | |||
| // | |||
| // Lol Engine | |||
| // | |||
| // Copyright: (c) 2010-2012 Sam Hocevar <sam@hocevar.net> | |||
| // (c) 2009-2012 Cédric Lecacheur <jordx@free.fr> | |||
| // (c) 2009-2012 Benjamin Huet <huet.benjamin@gmail.com> | |||
| // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net> | |||
| // (c) 2009-2013 Cédric Lecacheur <jordx@free.fr> | |||
| // (c) 2009-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com> | |||
| // This program is free software; you can redistribute it and/or | |||
| // modify it under the terms of the Do What The Fuck You Want To | |||
| // Public License, Version 2, as published by Sam Hocevar. See | |||
| @@ -32,10 +32,26 @@ public: | |||
| void MeshConvert(Shader* ProvidedShader = NULL); | |||
| void Render(mat4 const &model, float damage = 0.f); | |||
| private: | |||
| void UpdateVertexDict(Array< int, int > &vertex_dict); | |||
| //DEBUG | |||
| public: | |||
| #define CSG_UNION 0 | |||
| #define CSG_SUBSTRACT 1 | |||
| #define CSG_AND 2 | |||
| #define CSG_XOR 3 | |||
| void MeshCsg(int csg_operation); | |||
| void CsgUnion() { MeshCsg(CSG_UNION); } | |||
| void CsgSubstract() { MeshCsg(CSG_SUBSTRACT); } | |||
| void CsgAnd() { MeshCsg(CSG_AND); } | |||
| void CsgXor() { MeshCsg(CSG_XOR); } | |||
| public: | |||
| void OpenBrace(); | |||
| void CloseBrace(); | |||
| void ToggleScaleWinding(); | |||
| void ToggleScaleWinding(); | |||
| void SetCurColor(vec4 const &color); | |||
| void SetCurColor2(vec4 const &color); | |||
| @@ -92,9 +108,11 @@ public: | |||
| private: | |||
| vec4 m_color, m_color2; | |||
| Array<uint16_t> m_indices; | |||
| //<coord, norm, color> | |||
| Array<vec3, vec3, vec4> m_vert; | |||
| //<vert count, indices count> | |||
| Array<int, int> m_cursors; | |||
| bool m_ignore_winding_on_scale; | |||
| bool m_ignore_winding_on_scale; | |||
| /* FIXME: put this in a separate class so that we can copy meshes. */ | |||
| struct | |||
| @@ -65,7 +65,7 @@ void main(void) | |||
| /* World properties */ | |||
| float ambient_mul = 0.5; | |||
| vec3 ambient_color = vec3(0.0, 0.0, 0.0); | |||
| vec3 ambient_color = vec3(0.5, 0.5, 0.5); | |||
| vec3 diffuse_color = vec3(0.4, 0.4, 0.4); | |||
| vec3 specular_color = vec3(1.0, 1.0, 0.6); | |||
| @@ -1,8 +1,8 @@ | |||
| /* A Bison parser, made by GNU Bison 2.5. */ | |||
| /* A Bison parser, made by GNU Bison 2.4.2. */ | |||
| /* Skeleton interface for Bison LALR(1) parsers in C++ | |||
| Copyright (C) 2002-2011 Free Software Foundation, Inc. | |||
| Copyright (C) 2002-2010 Free Software Foundation, Inc. | |||
| This program is free software: you can redistribute it and/or modify | |||
| it under the terms of the GNU General Public License as published by | |||
| @@ -40,6 +40,20 @@ | |||
| #include <string> | |||
| #include <iostream> | |||
| #include "stack.hh" | |||
| namespace lol { | |||
| /* Line 34 of lalr1.cc */ | |||
| #line 49 "generated/easymesh-parser.h" | |||
| class position; | |||
| class location; | |||
| } // lol | |||
| /* Line 34 of lalr1.cc */ | |||
| #line 56 "generated/easymesh-parser.h" | |||
| #include "location.hh" | |||
| /* Enabling traces. */ | |||
| @@ -60,11 +74,30 @@ | |||
| # define YYTOKEN_TABLE 0 | |||
| #endif | |||
| /* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N]. | |||
| If N is 0, then set CURRENT to the empty location which ends | |||
| the previous symbol: RHS[0] (always defined). */ | |||
| #ifndef YYLLOC_DEFAULT | |||
| # define YYLLOC_DEFAULT(Current, Rhs, N) \ | |||
| do { \ | |||
| if (N) \ | |||
| { \ | |||
| (Current).begin = (Rhs)[1].begin; \ | |||
| (Current).end = (Rhs)[N].end; \ | |||
| } \ | |||
| else \ | |||
| { \ | |||
| (Current).begin = (Current).end = (Rhs)[0].end; \ | |||
| } \ | |||
| } while (false) | |||
| #endif | |||
| namespace lol { | |||
| /* Line 35 of lalr1.cc */ | |||
| #line 68 "generated/easymesh-parser.h" | |||
| /* Line 34 of lalr1.cc */ | |||
| #line 101 "generated/easymesh-parser.h" | |||
| /// A Bison parser. | |||
| class EasyMeshParser | |||
| @@ -75,7 +108,7 @@ namespace lol { | |||
| union semantic_type | |||
| { | |||
| /* Line 35 of lalr1.cc */ | |||
| /* Line 34 of lalr1.cc */ | |||
| #line 36 "easymesh/easymesh-parser.y" | |||
| float fval; | |||
| @@ -85,8 +118,8 @@ namespace lol { | |||
| /* Line 35 of lalr1.cc */ | |||
| #line 90 "generated/easymesh-parser.h" | |||
| /* Line 34 of lalr1.cc */ | |||
| #line 123 "generated/easymesh-parser.h" | |||
| }; | |||
| #else | |||
| typedef YYSTYPE semantic_type; | |||
| @@ -119,23 +152,27 @@ namespace lol { | |||
| T_TRANSLATE = 275, | |||
| T_SCALE = 276, | |||
| T_TOGGLESCALEWINDING = 277, | |||
| T_CHAMFER = 278, | |||
| T_CYLINDER = 279, | |||
| T_BOX = 280, | |||
| T_SMOOTHCHAMFBOX = 281, | |||
| T_FLATCHAMFBOX = 282, | |||
| T_SPHERE = 283, | |||
| T_CAPSULE = 284, | |||
| T_STAR = 285, | |||
| T_EXPANDEDSTAR = 286, | |||
| T_DISC = 287, | |||
| T_TRIANGLE = 288, | |||
| T_QUAD = 289, | |||
| T_COG = 290, | |||
| T_TORUS = 291, | |||
| T_ERROR = 292, | |||
| NUMBER = 293, | |||
| COLOR = 294 | |||
| T_CSGUNION = 278, | |||
| T_CSGSUBSTRACT = 279, | |||
| T_CSGAND = 280, | |||
| T_CSGXOR = 281, | |||
| T_CHAMFER = 282, | |||
| T_CYLINDER = 283, | |||
| T_BOX = 284, | |||
| T_SMOOTHCHAMFBOX = 285, | |||
| T_FLATCHAMFBOX = 286, | |||
| T_SPHERE = 287, | |||
| T_CAPSULE = 288, | |||
| T_STAR = 289, | |||
| T_EXPANDEDSTAR = 290, | |||
| T_DISC = 291, | |||
| T_TRIANGLE = 292, | |||
| T_QUAD = 293, | |||
| T_COG = 294, | |||
| T_TORUS = 295, | |||
| T_ERROR = 296, | |||
| NUMBER = 297, | |||
| COLOR = 298 | |||
| }; | |||
| }; | |||
| @@ -209,14 +246,6 @@ namespace lol { | |||
| /// The location stack. | |||
| location_stack_type yylocation_stack_; | |||
| /// Whether the given \c yypact_ value indicates a defaulted state. | |||
| /// \param yyvalue the value to check | |||
| static bool yy_pact_value_is_default_ (int yyvalue); | |||
| /// Whether the given \c yytable_ value indicates a syntax error. | |||
| /// \param yyvalue the value to check | |||
| static bool yy_table_value_is_error_ (int yyvalue); | |||
| /// Internal symbol numbers. | |||
| typedef unsigned char token_number_type; | |||
| /* Tables. */ | |||
| @@ -224,7 +253,7 @@ namespace lol { | |||
| static const signed char yypact_[]; | |||
| static const signed char yypact_ninf_; | |||
| /// For a state, default reduction number. | |||
| /// For a state, default rule to reduce. | |||
| /// Unless\a yytable_ specifies something else to do. | |||
| /// Zero means the default is an error. | |||
| static const unsigned char yydefact_[]; | |||
| @@ -255,8 +284,10 @@ namespace lol { | |||
| static const char* const yytname_[]; | |||
| #endif | |||
| #if YYERROR_VERBOSE | |||
| /// Convert the symbol name \a n to a form suitable for a diagnostic. | |||
| static std::string yytnamerr_ (const char *n); | |||
| virtual std::string yytnamerr_ (const char *n); | |||
| #endif | |||
| #if YYDEBUG | |||
| /// A type to store symbol numbers and -1. | |||
| @@ -314,8 +345,8 @@ namespace lol { | |||
| } // lol | |||
| /* Line 35 of lalr1.cc */ | |||
| #line 319 "generated/easymesh-parser.h" | |||
| /* Line 34 of lalr1.cc */ | |||
| #line 350 "generated/easymesh-parser.h" | |||
| @@ -330,8 +330,8 @@ typedef unsigned char YY_CHAR; | |||
| *yy_cp = '\0'; \ | |||
| (yy_c_buf_p) = yy_cp; | |||
| #define YY_NUM_RULES 46 | |||
| #define YY_END_OF_BUFFER 47 | |||
| #define YY_NUM_RULES 50 | |||
| #define YY_END_OF_BUFFER 51 | |||
| /* This struct is not used in this scanner, | |||
| but its presence is necessary. */ | |||
| struct yy_trans_info | |||
| @@ -339,16 +339,16 @@ struct yy_trans_info | |||
| flex_int32_t yy_verify; | |||
| flex_int32_t yy_nxt; | |||
| }; | |||
| static yyconst flex_int16_t yy_accept[75] = | |||
| static yyconst flex_int16_t yy_accept[81] = | |||
| { 0, | |||
| 0, 0, 47, 45, 44, 43, 45, 45, 40, 45, | |||
| 39, 41, 42, 45, 45, 45, 45, 17, 7, 0, | |||
| 0, 39, 39, 0, 22, 23, 26, 0, 0, 29, | |||
| 30, 33, 3, 19, 20, 21, 8, 9, 10, 1, | |||
| 14, 15, 16, 0, 0, 4, 5, 6, 0, 0, | |||
| 39, 0, 25, 27, 0, 0, 0, 34, 2, 11, | |||
| 12, 13, 18, 35, 24, 28, 31, 32, 36, 0, | |||
| 37, 0, 38, 0 | |||
| 0, 0, 51, 49, 48, 47, 49, 49, 44, 49, | |||
| 43, 45, 46, 49, 49, 49, 49, 17, 7, 0, | |||
| 0, 43, 43, 0, 26, 27, 30, 0, 0, 33, | |||
| 34, 37, 3, 0, 19, 20, 21, 8, 9, 10, | |||
| 1, 14, 15, 16, 0, 0, 4, 5, 6, 0, | |||
| 0, 43, 0, 29, 31, 0, 0, 0, 38, 0, | |||
| 2, 11, 12, 13, 18, 39, 28, 32, 35, 36, | |||
| 24, 23, 22, 25, 40, 0, 41, 0, 42, 0 | |||
| } ; | |||
| static yyconst flex_int32_t yy_ec[256] = | |||
| @@ -365,8 +365,8 @@ static yyconst flex_int32_t yy_ec[256] = | |||
| 11, 1, 12, 1, 1, 1, 13, 14, 15, 16, | |||
| 17, 18, 19, 20, 1, 1, 1, 1, 21, 1, | |||
| 22, 23, 24, 25, 26, 27, 1, 1, 28, 29, | |||
| 30, 31, 1, 1, 1, 1, 1, 1, 1, 1, | |||
| 22, 23, 24, 25, 26, 27, 28, 1, 29, 30, | |||
| 31, 32, 1, 1, 1, 1, 1, 1, 1, 1, | |||
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |||
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |||
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |||
| @@ -383,76 +383,78 @@ static yyconst flex_int32_t yy_ec[256] = | |||
| 1, 1, 1, 1, 1 | |||
| } ; | |||
| static yyconst flex_int32_t yy_meta[32] = | |||
| static yyconst flex_int32_t yy_meta[33] = | |||
| { 0, | |||
| 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, | |||
| 1, 1, 2, 2, 2, 2, 2, 2, 1, 1, | |||
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |||
| 1 | |||
| 1, 1 | |||
| } ; | |||
| static yyconst flex_int16_t yy_base[83] = | |||
| static yyconst flex_int16_t yy_base[89] = | |||
| { 0, | |||
| 0, 0, 102, 103, 103, 103, 0, 25, 27, 93, | |||
| 29, 103, 103, 33, 80, 11, 14, 23, 48, 0, | |||
| 91, 48, 54, 61, 103, 57, 103, 72, 82, 103, | |||
| 57, 74, 103, 103, 103, 103, 103, 103, 103, 81, | |||
| 103, 103, 103, 52, 66, 103, 103, 103, 0, 85, | |||
| 84, 68, 103, 103, 76, 75, 68, 103, 103, 103, | |||
| 103, 103, 103, 0, 103, 103, 103, 103, 0, 0, | |||
| 0, 0, 103, 103, 85, 84, 83, 82, 73, 71, | |||
| 66, 61 | |||
| 0, 0, 109, 110, 110, 110, 0, 26, 28, 100, | |||
| 30, 110, 110, 34, 19, 11, 23, 41, 61, 0, | |||
| 99, 58, 59, 72, 110, 44, 110, 80, 90, 110, | |||
| 47, 82, 110, 84, 110, 110, 110, 110, 110, 110, | |||
| 88, 110, 110, 110, 51, 71, 110, 110, 110, 0, | |||
| 90, 88, 72, 110, 110, 80, 76, 69, 110, 71, | |||
| 110, 110, 110, 110, 110, 0, 110, 110, 110, 110, | |||
| 110, 110, 110, 110, 0, 0, 0, 0, 110, 110, | |||
| 86, 84, 83, 77, 62, 57, 44, 42 | |||
| } ; | |||
| static yyconst flex_int16_t yy_def[83] = | |||
| static yyconst flex_int16_t yy_def[89] = | |||
| { 0, | |||
| 74, 1, 74, 74, 74, 74, 75, 74, 74, 74, | |||
| 74, 74, 74, 74, 74, 74, 74, 74, 74, 76, | |||
| 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, | |||
| 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, | |||
| 74, 74, 74, 74, 74, 74, 74, 74, 77, 74, | |||
| 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, | |||
| 74, 74, 74, 78, 74, 74, 74, 74, 79, 80, | |||
| 81, 82, 74, 0, 74, 74, 74, 74, 74, 74, | |||
| 74, 74 | |||
| 80, 1, 80, 80, 80, 80, 81, 80, 80, 80, | |||
| 80, 80, 80, 80, 80, 80, 80, 80, 80, 82, | |||
| 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, | |||
| 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, | |||
| 80, 80, 80, 80, 80, 80, 80, 80, 80, 83, | |||
| 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, | |||
| 80, 80, 80, 80, 80, 84, 80, 80, 80, 80, | |||
| 80, 80, 80, 80, 85, 86, 87, 88, 80, 0, | |||
| 80, 80, 80, 80, 80, 80, 80, 80 | |||
| } ; | |||
| static yyconst flex_int16_t yy_nxt[135] = | |||
| static yyconst flex_int16_t yy_nxt[143] = | |||
| { 0, | |||
| 4, 5, 6, 7, 8, 9, 10, 11, 4, 4, | |||
| 12, 13, 14, 4, 15, 4, 4, 4, 4, 4, | |||
| 16, 4, 4, 4, 17, 18, 19, 4, 4, 4, | |||
| 4, 21, 22, 21, 22, 21, 22, 40, 24, 34, | |||
| 35, 36, 37, 38, 39, 24, 25, 26, 27, 28, | |||
| 29, 41, 42, 43, 21, 22, 30, 24, 31, 32, | |||
| 44, 23, 73, 24, 24, 50, 50, 72, 51, 52, | |||
| 24, 56, 71, 45, 70, 53, 46, 47, 48, 57, | |||
| 60, 61, 62, 69, 64, 49, 20, 68, 67, 66, | |||
| 65, 51, 51, 63, 59, 58, 55, 54, 23, 33, | |||
| 23, 74, 3, 74, 74, 74, 74, 74, 74, 74, | |||
| 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, | |||
| 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, | |||
| 74, 74, 74, 74 | |||
| 4, 4, 21, 22, 21, 22, 21, 22, 33, 24, | |||
| 35, 36, 37, 79, 34, 78, 24, 25, 26, 27, | |||
| 28, 29, 38, 39, 40, 41, 53, 30, 77, 31, | |||
| 32, 57, 54, 76, 21, 22, 23, 24, 24, 58, | |||
| 42, 43, 44, 45, 24, 24, 51, 51, 75, 52, | |||
| 62, 63, 64, 71, 66, 50, 46, 20, 70, 69, | |||
| 47, 48, 49, 68, 67, 52, 72, 52, 73, 65, | |||
| 74, 61, 60, 59, 56, 55, 23, 23, 80, 3, | |||
| 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, | |||
| 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, | |||
| 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, | |||
| 80, 80 | |||
| } ; | |||
| static yyconst flex_int16_t yy_chk[135] = | |||
| static yyconst flex_int16_t yy_chk[143] = | |||
| { 0, | |||
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |||
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |||
| 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, | |||
| 1, 8, 8, 9, 9, 11, 11, 18, 11, 16, | |||
| 16, 16, 17, 17, 17, 11, 14, 14, 14, 14, | |||
| 14, 18, 18, 18, 22, 22, 14, 22, 14, 14, | |||
| 19, 23, 82, 23, 22, 24, 24, 81, 24, 26, | |||
| 23, 31, 80, 19, 79, 26, 19, 19, 19, 31, | |||
| 44, 44, 44, 78, 77, 76, 75, 57, 56, 55, | |||
| 52, 51, 50, 45, 40, 32, 29, 28, 21, 15, | |||
| 10, 3, 74, 74, 74, 74, 74, 74, 74, 74, | |||
| 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, | |||
| 74, 74, 74, 74, 74, 74, 74, 74, 74, 74, | |||
| 74, 74, 74, 74 | |||
| 1, 1, 8, 8, 9, 9, 11, 11, 15, 11, | |||
| 16, 16, 16, 88, 15, 87, 11, 14, 14, 14, | |||
| 14, 14, 17, 17, 17, 18, 26, 14, 86, 14, | |||
| 14, 31, 26, 85, 22, 22, 23, 22, 23, 31, | |||
| 18, 18, 18, 19, 22, 23, 24, 24, 84, 24, | |||
| 45, 45, 45, 60, 83, 82, 19, 81, 58, 57, | |||
| 19, 19, 19, 56, 53, 52, 60, 51, 60, 46, | |||
| 60, 41, 34, 32, 29, 28, 21, 10, 3, 80, | |||
| 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, | |||
| 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, | |||
| 80, 80, 80, 80, 80, 80, 80, 80, 80, 80, | |||
| 80, 80 | |||
| } ; | |||
| /* The intent behind this definition is that it'll catch | |||
| @@ -467,9 +469,9 @@ static yyconst flex_int16_t yy_chk[135] = | |||
| // | |||
| // Lol Engine | |||
| // | |||
| // Copyright: (c) 2010-2012 Sam Hocevar <sam@hocevar.net> | |||
| // (c) 2009-2012 Cédric Lecacheur <jordx@free.fr> | |||
| // (c) 2009-2012 Benjamin Huet <huet.benjamin@gmail.com> | |||
| // Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net> | |||
| // (c) 2009-2013 Cédric Lecacheur <jordx@free.fr> | |||
| // (c) 2009-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com> | |||
| // This program is free software; you can redistribute it and/or | |||
| // modify it under the terms of the Do What The Fuck You Want To | |||
| // Public License, Version 2, as published by Sam Hocevar. See | |||
| @@ -501,7 +503,7 @@ typedef lol::EasyMeshParser::token_type token_type; | |||
| #define yyterminate() return token::T_END | |||
| #define YY_NO_UNISTD_H | |||
| #define YY_USER_ACTION yylloc->columns(yyleng); | |||
| #line 505 "generated/easymesh-scanner.cpp" | |||
| #line 507 "generated/easymesh-scanner.cpp" | |||
| #define INITIAL 0 | |||
| @@ -614,7 +616,7 @@ YY_DECL | |||
| yylloc->step(); | |||
| #line 618 "generated/easymesh-scanner.cpp" | |||
| #line 620 "generated/easymesh-scanner.cpp" | |||
| if ( !(yy_init) ) | |||
| { | |||
| @@ -667,13 +669,13 @@ yy_match: | |||
| while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) | |||
| { | |||
| yy_current_state = (int) yy_def[yy_current_state]; | |||
| if ( yy_current_state >= 75 ) | |||
| if ( yy_current_state >= 81 ) | |||
| yy_c = yy_meta[(unsigned int) yy_c]; | |||
| } | |||
| yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; | |||
| ++yy_cp; | |||
| } | |||
| while ( yy_current_state != 74 ); | |||
| while ( yy_current_state != 80 ); | |||
| yy_cp = (yy_last_accepting_cpos); | |||
| yy_current_state = (yy_last_accepting_state); | |||
| @@ -801,71 +803,91 @@ YY_RULE_SETUP | |||
| case 22: | |||
| YY_RULE_SETUP | |||
| #line 74 "easymesh/easymesh-scanner.l" | |||
| { return token::T_BOX; } | |||
| { return token::T_CSGUNION; } | |||
| YY_BREAK | |||
| case 23: | |||
| YY_RULE_SETUP | |||
| #line 75 "easymesh/easymesh-scanner.l" | |||
| { return token::T_CYLINDER; } | |||
| { return token::T_CSGSUBSTRACT; } | |||
| YY_BREAK | |||
| case 24: | |||
| YY_RULE_SETUP | |||
| #line 76 "easymesh/easymesh-scanner.l" | |||
| { return token::T_CAPSULE; } | |||
| { return token::T_CSGAND; } | |||
| YY_BREAK | |||
| case 25: | |||
| YY_RULE_SETUP | |||
| #line 77 "easymesh/easymesh-scanner.l" | |||
| { return token::T_COG; } | |||
| { return token::T_CSGXOR; } | |||
| YY_BREAK | |||
| case 26: | |||
| YY_RULE_SETUP | |||
| #line 78 "easymesh/easymesh-scanner.l" | |||
| { return token::T_DISC; } | |||
| #line 79 "easymesh/easymesh-scanner.l" | |||
| { return token::T_BOX; } | |||
| YY_BREAK | |||
| case 27: | |||
| YY_RULE_SETUP | |||
| #line 79 "easymesh/easymesh-scanner.l" | |||
| { return token::T_EXPANDEDSTAR; } | |||
| #line 80 "easymesh/easymesh-scanner.l" | |||
| { return token::T_CYLINDER; } | |||
| YY_BREAK | |||
| case 28: | |||
| YY_RULE_SETUP | |||
| #line 80 "easymesh/easymesh-scanner.l" | |||
| { return token::T_FLATCHAMFBOX; } | |||
| #line 81 "easymesh/easymesh-scanner.l" | |||
| { return token::T_CAPSULE; } | |||
| YY_BREAK | |||
| case 29: | |||
| YY_RULE_SETUP | |||
| #line 81 "easymesh/easymesh-scanner.l" | |||
| { return token::T_QUAD; } | |||
| #line 82 "easymesh/easymesh-scanner.l" | |||
| { return token::T_COG; } | |||
| YY_BREAK | |||
| case 30: | |||
| YY_RULE_SETUP | |||
| #line 82 "easymesh/easymesh-scanner.l" | |||
| { return token::T_STAR; } | |||
| #line 83 "easymesh/easymesh-scanner.l" | |||
| { return token::T_DISC; } | |||
| YY_BREAK | |||
| case 31: | |||
| YY_RULE_SETUP | |||
| #line 83 "easymesh/easymesh-scanner.l" | |||
| { return token::T_SMOOTHCHAMFBOX; } | |||
| #line 84 "easymesh/easymesh-scanner.l" | |||
| { return token::T_EXPANDEDSTAR; } | |||
| YY_BREAK | |||
| case 32: | |||
| YY_RULE_SETUP | |||
| #line 84 "easymesh/easymesh-scanner.l" | |||
| { return token::T_SPHERE; } | |||
| #line 85 "easymesh/easymesh-scanner.l" | |||
| { return token::T_FLATCHAMFBOX; } | |||
| YY_BREAK | |||
| case 33: | |||
| YY_RULE_SETUP | |||
| #line 85 "easymesh/easymesh-scanner.l" | |||
| { return token::T_TRIANGLE; } | |||
| #line 86 "easymesh/easymesh-scanner.l" | |||
| { return token::T_QUAD; } | |||
| YY_BREAK | |||
| case 34: | |||
| YY_RULE_SETUP | |||
| #line 86 "easymesh/easymesh-scanner.l" | |||
| { return token::T_TORUS; } | |||
| #line 87 "easymesh/easymesh-scanner.l" | |||
| { return token::T_STAR; } | |||
| YY_BREAK | |||
| case 35: | |||
| YY_RULE_SETUP | |||
| #line 88 "easymesh/easymesh-scanner.l" | |||
| { return token::T_SMOOTHCHAMFBOX; } | |||
| YY_BREAK | |||
| case 36: | |||
| YY_RULE_SETUP | |||
| #line 89 "easymesh/easymesh-scanner.l" | |||
| { return token::T_SPHERE; } | |||
| YY_BREAK | |||
| case 37: | |||
| YY_RULE_SETUP | |||
| #line 90 "easymesh/easymesh-scanner.l" | |||
| { return token::T_TRIANGLE; } | |||
| YY_BREAK | |||
| case 38: | |||
| YY_RULE_SETUP | |||
| #line 91 "easymesh/easymesh-scanner.l" | |||
| { return token::T_TORUS; } | |||
| YY_BREAK | |||
| case 39: | |||
| YY_RULE_SETUP | |||
| #line 93 "easymesh/easymesh-scanner.l" | |||
| { | |||
| uint32_t tmp = std::strtol(yytext + 1, NULL, 16); | |||
| yylval->u32val = 0x11000000u * (tmp >> 8) | |||
| @@ -874,9 +896,9 @@ YY_RULE_SETUP | |||
| | 0x000000ffu; | |||
| return token::COLOR; } | |||
| YY_BREAK | |||
| case 36: | |||
| case 40: | |||
| YY_RULE_SETUP | |||
| #line 95 "easymesh/easymesh-scanner.l" | |||
| #line 100 "easymesh/easymesh-scanner.l" | |||
| { | |||
| uint32_t tmp = std::strtol(yytext + 1, NULL, 16); | |||
| yylval->u32val = 0x11000000u * (tmp >> 12) | |||
| @@ -885,64 +907,64 @@ YY_RULE_SETUP | |||
| | 0x00000011u * (tmp & 0xf); | |||
| return token::COLOR; } | |||
| YY_BREAK | |||
| case 37: | |||
| case 41: | |||
| YY_RULE_SETUP | |||
| #line 102 "easymesh/easymesh-scanner.l" | |||
| #line 107 "easymesh/easymesh-scanner.l" | |||
| { | |||
| yylval->u32val = 0xffu | |||
| | 0x100u * (uint32_t)std::strtol(yytext + 1, NULL, 16); | |||
| return token::COLOR; } | |||
| YY_BREAK | |||
| case 38: | |||
| case 42: | |||
| YY_RULE_SETUP | |||
| #line 106 "easymesh/easymesh-scanner.l" | |||
| #line 111 "easymesh/easymesh-scanner.l" | |||
| { | |||
| yylval->u32val = (uint32_t)std::strtol(yytext + 1, NULL, 16); | |||
| return token::COLOR; } | |||
| YY_BREAK | |||
| case 39: | |||
| case 43: | |||
| YY_RULE_SETUP | |||
| #line 109 "easymesh/easymesh-scanner.l" | |||
| #line 114 "easymesh/easymesh-scanner.l" | |||
| { | |||
| yylval->fval = std::atof(yytext); return token::NUMBER; } | |||
| YY_BREAK | |||
| case 40: | |||
| case 44: | |||
| YY_RULE_SETUP | |||
| #line 111 "easymesh/easymesh-scanner.l" | |||
| #line 116 "easymesh/easymesh-scanner.l" | |||
| { return token_type('-'); } | |||
| YY_BREAK | |||
| case 41: | |||
| case 45: | |||
| YY_RULE_SETUP | |||
| #line 112 "easymesh/easymesh-scanner.l" | |||
| #line 117 "easymesh/easymesh-scanner.l" | |||
| { return token_type('['); } | |||
| YY_BREAK | |||
| case 42: | |||
| case 46: | |||
| YY_RULE_SETUP | |||
| #line 113 "easymesh/easymesh-scanner.l" | |||
| #line 118 "easymesh/easymesh-scanner.l" | |||
| { return token_type(']'); } | |||
| YY_BREAK | |||
| case 43: | |||
| case 47: | |||
| YY_RULE_SETUP | |||
| #line 114 "easymesh/easymesh-scanner.l" | |||
| #line 119 "easymesh/easymesh-scanner.l" | |||
| { /* ignore this */ } | |||
| YY_BREAK | |||
| case 44: | |||
| /* rule 44 can match eol */ | |||
| case 48: | |||
| /* rule 48 can match eol */ | |||
| YY_RULE_SETUP | |||
| #line 115 "easymesh/easymesh-scanner.l" | |||
| #line 120 "easymesh/easymesh-scanner.l" | |||
| { /* ignore this */ } | |||
| YY_BREAK | |||
| case 45: | |||
| case 49: | |||
| YY_RULE_SETUP | |||
| #line 116 "easymesh/easymesh-scanner.l" | |||
| #line 121 "easymesh/easymesh-scanner.l" | |||
| { return token::T_ERROR; } | |||
| YY_BREAK | |||
| case 46: | |||
| case 50: | |||
| YY_RULE_SETUP | |||
| #line 118 "easymesh/easymesh-scanner.l" | |||
| #line 123 "easymesh/easymesh-scanner.l" | |||
| ECHO; | |||
| YY_BREAK | |||
| #line 946 "generated/easymesh-scanner.cpp" | |||
| #line 968 "generated/easymesh-scanner.cpp" | |||
| case YY_STATE_EOF(INITIAL): | |||
| yyterminate(); | |||
| @@ -1324,7 +1346,7 @@ int yyFlexLexer::yy_get_next_buffer() | |||
| while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) | |||
| { | |||
| yy_current_state = (int) yy_def[yy_current_state]; | |||
| if ( yy_current_state >= 75 ) | |||
| if ( yy_current_state >= 81 ) | |||
| yy_c = yy_meta[(unsigned int) yy_c]; | |||
| } | |||
| yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; | |||
| @@ -1352,11 +1374,11 @@ int yyFlexLexer::yy_get_next_buffer() | |||
| while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) | |||
| { | |||
| yy_current_state = (int) yy_def[yy_current_state]; | |||
| if ( yy_current_state >= 75 ) | |||
| if ( yy_current_state >= 81 ) | |||
| yy_c = yy_meta[(unsigned int) yy_c]; | |||
| } | |||
| yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; | |||
| yy_is_jam = (yy_current_state == 74); | |||
| yy_is_jam = (yy_current_state == 80); | |||
| return yy_is_jam ? 0 : yy_current_state; | |||
| } | |||
| @@ -1843,7 +1865,7 @@ void EasyMeshfree (void * ptr ) | |||
| #define YYTABLES_NAME "yytables" | |||
| #line 118 "easymesh/easymesh-scanner.l" | |||
| #line 123 "easymesh/easymesh-scanner.l" | |||
| @@ -240,6 +240,7 @@ | |||
| <ClCompile Include="debug\record.cpp" /> | |||
| <ClCompile Include="debug\stats.cpp" /> | |||
| <ClCompile Include="dict.cpp" /> | |||
| <ClCompile Include="easymesh\csgbsp.cpp" /> | |||
| <ClCompile Include="easymesh\easymesh-compiler.cpp" /> | |||
| <ClCompile Include="easymesh\easymesh.cpp" /> | |||
| <ClCompile Include="eglapp.cpp" /> | |||
| @@ -555,6 +556,7 @@ | |||
| <ClInclude Include="debug\record.h" /> | |||
| <ClInclude Include="debug\stats.h" /> | |||
| <ClInclude Include="dict.h" /> | |||
| <ClInclude Include="easymesh\csgbsp.h" /> | |||
| <ClInclude Include="easymesh\easymesh-compiler.h" /> | |||
| <ClInclude Include="easymesh\easymesh.h" /> | |||
| <ClInclude Include="eglapp.h" /> | |||
| @@ -657,6 +657,9 @@ | |||
| <ClCompile Include="math\geometry.cpp"> | |||
| <Filter>math</Filter> | |||
| </ClCompile> | |||
| <ClCompile Include="easymesh\csgbsp.cpp"> | |||
| <Filter>easymesh</Filter> | |||
| </ClCompile> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <ClInclude Include="image\image.h"> | |||
| @@ -1634,6 +1637,9 @@ | |||
| <ClInclude Include="lol\math\geometry.h"> | |||
| <Filter>lol\math</Filter> | |||
| </ClInclude> | |||
| <ClInclude Include="easymesh\csgbsp.h"> | |||
| <Filter>easymesh</Filter> | |||
| </ClInclude> | |||
| </ItemGroup> | |||
| <ItemGroup> | |||
| <LolFxCompile Include="gpu\emptymaterial.lolfx"> | |||
| @@ -1,7 +1,8 @@ | |||
| // | |||
| // Lol Engine - EasyMesh tutorial | |||
| // | |||
| // Copyright: (c) 2011-2012 Sam Hocevar <sam@hocevar.net> | |||
| // Copyright: (c) 2011-2013 Sam Hocevar <sam@hocevar.net> | |||
| // (c) 2012-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com> | |||
| // This program is free software; you can redistribute it and/or | |||
| // modify it under the terms of the Do What The Fuck You Want To | |||
| // Public License, Version 2, as published by Sam Hocevar. See | |||
| @@ -28,20 +29,30 @@ public: | |||
| m_gears.Push(EasyMesh(), mat4(1.0f), 180.0f / 18); | |||
| m_gears.Push(EasyMesh(), mat4(1.0f), 180.0f / 18); | |||
| m_gears[0].m1.Compile("sc#f9f scb#f9f acg 12 10 5 5 20 20 5 5 0.1 0 s .1 .1 .1"); | |||
| m_gears[0].m1.Compile("[sc#00f ab 8 1 8 ty -.25]\ | |||
| [sc#f9f scb#f9f acg 12 10 5 5 20 20 5 5 0.1 0 s .1 .1 .1 ty -.1 csgu]\ | |||
| [sc#fff scb#000 acg 12 10 10 10 20 20 5 5 0.1 0 s .05 .05 .05 tx -1.5 ty .3 csgu]\ | |||
| [sc#00f ab 5 3 9 tx 2.5 csgs]\ | |||
| [[ sc#fff ab 3 1.4 2 tx -2 tz -2 \ | |||
| [sc#fff ab 2.1 .7 1.1 ty .5 tx -1.4 tz -1.4 csgs] mz] csgu] \ | |||
| "); | |||
| //m_gears[0].m1.Compile("[sc#f9f scb#f9f acg 12 10 5 5 20 20 5 5 0.1 0 s .1 .1 .1 [sc#00f ab 3 1 2 ty .25 tx 1 csgs]]"); | |||
| m_gears[1].m1.Compile("sc#ff9 scb#ff9 acg 54 10 95 95 90 90 -5 -5 0.1 0 s .1 .1 .1"); | |||
| m_gears[2].m1.Compile("sc#9ff scb#9ff acg 18 10 5 5 30 30 5 5 0.1 0 s .1 .1 .1"); | |||
| m_gears[3].m1.Compile("sc#9ff scb#9ff acg 18 10 5 5 30 30 5 5 0.1 0 s .1 .1 .1"); | |||
| m_gears[4].m1.Compile("sc#9ff scb#9ff acg 18 10 5 5 30 30 5 5 0.1 0 s .1 .1 .1"); | |||
| //m_gears[2].m1.Compile("sc#9ff scb#9ff acg 18 10 5 5 30 30 5 5 0.1 0 s .1 .1 .1 [sc#00f scb#00f ab 2 2 2 tx 1.5]"); | |||
| //m_gears[3].m1.Compile("sc#9ff scb#9ff acg 18 10 5 5 30 30 5 5 0.1 0 s .1 .1 .1 [sc#00f scb#00f ab 2 2 2 tx 1.5]"); | |||
| //m_gears[4].m1.Compile("sc#9ff scb#9ff acg 18 10 5 5 30 30 5 5 0.1 0 s .1 .1 .1 [sc#00f scb#00f ab 2 2 2 tx 1.5]"); | |||
| m_gears[2].m1.Compile("[sc#0f0 ab 2 2 2 t .8 .8 .8 rx 20 ry 20 [sc#00f ab 2 2 2 tx 0 csgu]]"); | |||
| m_gears[3].m1.Compile("[sc#0f0 ab 2 2 2 t .8 .8 .8 rx 20 ry 20 [sc#00f ab 2 2 2 tx 0 csgs]]"); | |||
| m_gears[4].m1.Compile("[sc#0f0 ab 2 2 2 t .8 .8 .8 rx 20 ry 20 [sc#00f ab 2 2 2 tx 0 csga]]"); | |||
| m_angle = 0; | |||
| m_camera = new Camera(vec3(0.f, 600.f, 0.f), | |||
| vec3(0.f, 0.f, 0.f), | |||
| vec3(0, 1, 0)); | |||
| m_camera->SetPerspective(70.f, 960.f, 600.f, .1f, 1000.f); | |||
| m_camera->SetPerspective(30.f, 960.f, 600.f, .1f, 1000.f); | |||
| m_camera->SetTarget(vec3(0.f, -1.f, 0.f)); | |||
| m_camera->SetPosition(vec3(-15.f, 10.f, 0.f)); | |||
| m_camera->SetPosition(vec3(-15.f, 5.f, 0.f)); | |||
| Ticker::Ref(m_camera); | |||
| m_ready = false; | |||
| @@ -58,24 +69,28 @@ public: | |||
| m_angle += seconds * 70.0f; | |||
| m_mat = mat4::rotate(10.0f, vec3(0, 0, 1)) | |||
| * mat4::rotate(m_angle, vec3(0, 1, 0)); | |||
| m_gears[0].m3 += seconds * 150.0f; | |||
| m_gears[1].m3 += seconds * 150.0f * -2 / 9; | |||
| m_gears[2].m3 += seconds * 150.0f * -2 / 3; | |||
| m_gears[3].m3 += seconds * 150.0f * -2 / 3; | |||
| m_gears[4].m3 += seconds * 150.0f * -2 / 3; | |||
| m_gears[0].m2 = mat4::translate(vec3(0, 0, 0)) | |||
| * mat4::rotate(m_gears[0].m3, vec3(0, 1, 0)); | |||
| * mat4::rotate(100, vec3(0, 1, 0)); | |||
| // * mat4::rotate(m_angle, vec3(0, 1, 0)); | |||
| m_gears[0].m3 += seconds * 20.0f; | |||
| m_gears[1].m3 += seconds * 20.0f * -2 / 9; | |||
| m_gears[2].m3 += seconds * 20.0f * -2 / 3; | |||
| m_gears[3].m3 += seconds * 20.0f * -2 / 3; | |||
| m_gears[4].m3 += seconds * 20.0f * -2 / 3; | |||
| m_gears[0].m2 = mat4::translate(vec3(0, -1, 0)) | |||
| * mat4::rotate(m_gears[0].m3 - 130.0f, vec3(0, 1, 0)) | |||
| * mat4::rotate(40.0f, vec3(0, 0, 1)); | |||
| m_gears[1].m2 = mat4::translate(vec3(0, 0, 0)) | |||
| * mat4::rotate(m_gears[1].m3, vec3(0, 1, 0)); | |||
| m_gears[2].m2 = mat4::translate(vec3(0, 0, 5.5f)) | |||
| * mat4::rotate(m_gears[2].m3, vec3(0, 1, 0)); | |||
| * mat4::rotate(m_gears[2].m3 - 40.0f, vec3(0, 1, 0)) | |||
| * mat4::rotate(90.0f, vec3(0, 0, 1)); | |||
| m_gears[3].m2 = mat4::translate(vec3(5.5f * lol::sqrt(3.f) * 0.5f, 0, -5.5f * 0.5f)) | |||
| * mat4::rotate(m_gears[3].m3, vec3(0, 1, 0)); | |||
| * mat4::rotate(m_gears[3].m3 - 140.0f, vec3(0, 1, 0)) | |||
| * mat4::rotate(-70.0f, vec3(0, 0, 1)); | |||
| m_gears[4].m2 = mat4::translate(vec3(-5.5f * lol::sqrt(3.f) * 0.5f, 0, -5.5f * 0.5f)) | |||
| * mat4::rotate(m_gears[4].m3, vec3(0, 1, 0)); | |||
| * mat4::rotate(m_gears[4].m3 - 80.0f, vec3(0, 1, 0)); | |||
| } | |||
| virtual void TickDraw(float seconds) | |||