@@ -48,7 +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 T_RADIALJITTER | |||
%token T_CSGUNION T_CSGSUBSTRACT T_CSGAND T_CSGXOR | |||
%token T_CSGUNION T_CSGSUBSTRACT T_CSGSUBSTRACTLOSS T_CSGAND T_CSGXOR | |||
%token T_CHAMFER | |||
%token T_CYLINDER T_BOX T_SMOOTHCHAMFBOX T_FLATCHAMFBOX T_SPHERE T_CAPSULE | |||
@@ -139,6 +139,7 @@ transform_command: | |||
| T_TOGGLESCALEWINDING { mc.m_mesh.ToggleScaleWinding(); } | |||
| T_CSGUNION { mc.m_mesh.CsgUnion(); } | |||
| T_CSGSUBSTRACT { mc.m_mesh.CsgSubstract(); } | |||
| T_CSGSUBSTRACTLOSS { mc.m_mesh.CsgSubstractLoss(); } | |||
| T_CSGAND { mc.m_mesh.CsgAnd(); } | |||
| T_CSGXOR { mc.m_mesh.CsgXor(); } | |||
; | |||
@@ -74,6 +74,7 @@ rj { return token::T_RADIALJITTER; } | |||
csgu { return token::T_CSGUNION; } | |||
csgs { return token::T_CSGSUBSTRACT; } | |||
csgsl { return token::T_CSGSUBSTRACTLOSS; } | |||
csga { return token::T_CSGAND; } | |||
csgx { return token::T_CSGXOR; } | |||
@@ -207,7 +207,7 @@ void EasyMesh::UpdateVertexDict(Array< int, int > &vertex_dict) | |||
} | |||
} | |||
void EasyMesh::MeshCsg(int csg_operation) | |||
void EasyMesh::MeshCsg(CSGUsage csg_operation) | |||
{ | |||
//A vertex dictionnary for vertices on the same spot. | |||
Array< int, int > vertex_dict; | |||
@@ -309,26 +309,29 @@ void EasyMesh::MeshCsg(int csg_operation) | |||
//Triangle Kill Test | |||
if (//csgu : CSGUnion() -> m0_Outside + m1_Outside | |||
(csg_operation == CSG_UNION && tri_list[k].m1 == LEAF_BACK) || | |||
(csg_operation == CSGUsage::Union && tri_list[k].m1 == LEAF_BACK) || | |||
//csgs : CSGSubstract() -> m0_Outside + m1_Inside-inverted | |||
(csg_operation == CSG_SUBSTRACT && | |||
(csg_operation == CSGUsage::Substract && | |||
((mesh_id == 0 && tri_list[k].m1 == LEAF_BACK) || | |||
(mesh_id == 1 && tri_list[k].m1 == LEAF_FRONT))) || | |||
//csgs : CSGSubstractLoss() -> m0_Outside | |||
(csg_operation == CSGUsage::SubstractLoss && | |||
((mesh_id == 0 && tri_list[k].m1 == LEAF_BACK) || mesh_id == 1)) || | |||
//csga : CSGAnd() -> Inside + Inside | |||
(csg_operation == CSG_AND && tri_list[k].m1 == LEAF_FRONT)) | |||
(csg_operation == CSGUsage::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) || | |||
(csg_operation == CSGUsage::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)) | |||
(csg_operation == CSGUsage::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) | |||
if (csg_operation == CSGUsage::Xor) | |||
{ | |||
for (int l = 0; l < 3; l++) | |||
{ | |||
@@ -570,12 +573,13 @@ void EasyMesh::SetCurColor2(vec4 const &color) | |||
void EasyMesh::AddVertex(vec3 const &coord) | |||
{ | |||
//TODO : m_vert.Push(coord, vec3(0.f, 1.f, 0.f), m_color, ivec2(0), vec2(0)); | |||
m_vert.Push(coord, vec3(0.f, 1.f, 0.f), m_color); | |||
} | |||
void EasyMesh::AddDuplicateVertex(int i) | |||
{ | |||
m_vert.Push(m_vert[i].m1, vec3(0.f, 1.f, 0.f), m_vert[i].m3); | |||
m_vert << m_vert[i]; | |||
} | |||
void EasyMesh::AppendQuad(int i1, int i2, int i3, int i4, int base) | |||
@@ -769,7 +773,7 @@ void EasyMesh::DupAndScale(vec3 const &s) | |||
int tlen = m_indices.Count() - m_cursors.Last().m2; | |||
for (int i = 0; i < vlen; i++) | |||
m_vert << m_vert[m_cursors.Last().m1++]; | |||
AddDuplicateVertex(m_cursors.Last().m1++); | |||
for (int i = 0; i < tlen; i++) | |||
m_indices << m_indices[m_cursors.Last().m2++] + vlen; | |||
@@ -21,6 +21,24 @@ | |||
namespace lol | |||
{ | |||
/* A safe enum for MeshCSG operations. */ | |||
struct CSGUsage | |||
{ | |||
enum Value | |||
{ | |||
Union, | |||
Substract, | |||
SubstractLoss, //will remove B from A, but not add inverted B | |||
And, | |||
Xor, | |||
} | |||
m_value; | |||
inline CSGUsage(Value v) : m_value(v) {} | |||
inline operator Value() { return m_value; } | |||
}; | |||
class EasyMesh | |||
{ | |||
friend class EasyMeshParser; | |||
@@ -34,18 +52,18 @@ public: | |||
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); } | |||
//------------------------------------------------------------------------- | |||
//Mesh CSG operations | |||
//------------------------------------------------------------------------- | |||
private: | |||
void MeshCsg(CSGUsage csg_operation); | |||
public: | |||
void CsgUnion() { MeshCsg(CSGUsage::Union); } | |||
void CsgSubstract() { MeshCsg(CSGUsage::Substract); } | |||
void CsgSubstractLoss() { MeshCsg(CSGUsage::SubstractLoss); } | |||
void CsgAnd() { MeshCsg(CSGUsage::And); } | |||
void CsgXor() { MeshCsg(CSGUsage::Xor); } | |||
public: | |||
void OpenBrace(); | |||
@@ -65,17 +83,19 @@ private: | |||
void ComputeNormals(int start, int vcount); | |||
void SetVertColor(vec4 const &color); | |||
public: | |||
void SetCurVertNormal(vec3 const &normal); | |||
void SetCurVertColor(vec4 const &color); | |||
void RadialJitter(float r); | |||
public: | |||
//------------------------------------------------------------------------- | |||
//Mesh transform operations | |||
//------------------------------------------------------------------------- | |||
void Translate(vec3 const &v); | |||
void RotateX(float t); | |||
void RotateY(float t); | |||
void RotateZ(float t); | |||
void Rotate(float t, vec3 const &axis); | |||
void RadialJitter(float r); | |||
void TaperX(float y, float z, float xoff); | |||
void TaperY(float x, float z, float yoff); | |||
void TaperZ(float x, float y, float zoff); | |||
@@ -86,6 +106,9 @@ public: | |||
void DupAndScale(vec3 const &s); | |||
void Chamfer(float f); | |||
//------------------------------------------------------------------------- | |||
//Mesh shape operations | |||
//------------------------------------------------------------------------- | |||
void AppendCylinder(int nsides, float h, float r1, float r2, | |||
int dualside, int smooth); | |||
void AppendCapsule(int ndivisions, float h, float r); | |||
@@ -105,6 +128,11 @@ public: | |||
void AppendCog(int nbsides, float h, float r10, float r20, float r1, | |||
float r2, float r12, float r22, float sidemul, int offset); | |||
//------------------------------------------------------------------------- | |||
//TODO : Mesh Bone operations | |||
//------------------------------------------------------------------------- | |||
//void AddBone(int parent_id) {} | |||
//Convenience functions | |||
public: | |||
int GetVertexCount() { return m_vert.Count(); } | |||
@@ -113,10 +141,14 @@ public: | |||
private: | |||
vec4 m_color, m_color2; | |||
Array<uint16_t> m_indices; | |||
//TODO : <coord, norm, color, bone_id, bone_weight> | |||
//TODO : Array<vec3, vec3, vec4, ivec2, vec2> m_vert; | |||
//TODO : More bone blend support than 2 ? | |||
//<coord, norm, color> | |||
Array<vec3, vec3, vec4> m_vert; | |||
//<vert count, indices count> | |||
Array<int, int> m_cursors; | |||
//When this flag is up, negative scaling will not invert faces. | |||
bool m_ignore_winding_on_scale; | |||
/* FIXME: put this in a separate class so that we can copy meshes. */ | |||