Browse Source

Added VertexDictionnary object to manage vertices with same coord && connected vertices.

Added UVs system with and UVs generation test (not very conclusive)
legacy
Benjamin ‘Touky’ Huet touky 12 years ago
parent
commit
e4cf8211e4
9 changed files with 711 additions and 289 deletions
  1. +398
    -205
      src/easymesh/easymesh.cpp
  2. +64
    -4
      src/easymesh/easymesh.h
  3. +6
    -0
      src/easymesh/shiny.lolfx
  4. +5
    -76
      src/easymesh/shinydebugUV.lolfx
  5. +5
    -2
      src/video.cpp
  6. +36
    -1
      test/MeshViewer.cpp
  7. +3
    -0
      test/MeshViewer.vcxproj
  8. +11
    -1
      test/MeshViewerBuffer.txt
  9. +183
    -0
      test/shinyfur.lolfx

+ 398
- 205
src/easymesh/easymesh.cpp View File

@@ -45,28 +45,33 @@ LOLFX_RESOURCE_DECLARE(shiny_SK);
namespace lol
{

//-----------------------------------------------------------------------------
EasyMesh::EasyMesh()
: m_color(0), m_color2(0), m_ignore_winding_on_scale(0)
{
m_cursors.Push(0, 0);
}

//-----------------------------------------------------------------------------
bool EasyMesh::Compile(char const *command)
{
EasyMeshCompiler mc(*this);
return mc.ParseString(command);
}

//-----------------------------------------------------------------------------
void EasyMesh::OpenBrace()
{
m_cursors.Push(m_vert.Count(), m_indices.Count());
}

//-----------------------------------------------------------------------------
void EasyMesh::CloseBrace()
{
m_cursors.Pop();
}

//-----------------------------------------------------------------------------
void EasyMesh::MeshConvert(Shader* provided_shader)
{
for (int i = 0; i < DebugRenderMode::Max; i++)
@@ -88,6 +93,7 @@ void EasyMesh::MeshConvert(Shader* provided_shader)
m_gpu.shader << Shader::Create(LOLFX_RESOURCE_NAME(shinydebugUV));

m_gpu.modelview << m_gpu.shader.Last()->GetUniformLocation("in_ModelView");
m_gpu.invmodelview << m_gpu.shader.Last()->GetUniformLocation("in_Inv_ModelView");
m_gpu.view << m_gpu.shader.Last()->GetUniformLocation("in_View");
m_gpu.invview << m_gpu.shader.Last()->GetUniformLocation("in_Inv_View");
m_gpu.proj << m_gpu.shader.Last()->GetUniformLocation("in_Proj");
@@ -95,23 +101,49 @@ void EasyMesh::MeshConvert(Shader* provided_shader)
m_gpu.damage << m_gpu.shader.Last()->GetUniformLocation("in_Damage");
m_gpu.lights << m_gpu.shader.Last()->GetUniformLocation("u_Lights");
m_gpu.coord << m_gpu.shader.Last()->GetAttribLocation("in_Vertex",
VertexUsage::Position, 0);
VertexUsage::Position, 0);
m_gpu.norm << m_gpu.shader.Last()->GetAttribLocation("in_Normal",
VertexUsage::Normal, 0);
m_gpu.color << m_gpu.shader.Last()->GetAttribLocation("in_Color",
VertexUsage::Color, 0);
VertexUsage::Color, 0);
#if VERTEX_USEAGE == VU_BONES
//TODO : -- BONE SUPPORT --
#elif VERTEX_USEAGE == VU_TEX_UV
//UV SUPPORT --
m_gpu.tex_coord << m_gpu.shader.Last()->GetAttribLocation("in_TexCoord",
VertexUsage::TexCoord, 0);
#endif
}

#if VERTEX_USEAGE == VU_BONES
//TODO : -- BONE SUPPORT --
#elif VERTEX_USEAGE == VU_TEX_UV
//UV SUPPORT --
m_gpu.vdecl = new VertexDeclaration(
VertexStream<vec3,vec3,u8vec4,vec2>(VertexUsage::Position,
VertexUsage::Normal,
VertexUsage::Color,
VertexUsage::TexCoord));

Array<vec3,vec3,u8vec4,vec2> vertexlist;
for (int i = 0; i < m_vert.Count(); i++)
vertexlist.Push(m_vert[i].m1,
m_vert[i].m2,
(u8vec4)(m_vert[i].m3 * 255.f),
m_vert[i].m4);
#else
//-- VANILLA --
m_gpu.vdecl = new VertexDeclaration(
VertexStream<vec3,vec3,u8vec4>(VertexUsage::Position,
VertexUsage::Normal,
VertexUsage::Color));
VertexUsage::Normal,
VertexUsage::Color));

Array<vec3,vec3,u8vec4> vertexlist;
for (int i = 0; i < m_vert.Count(); i++)
vertexlist.Push(m_vert[i].m1,
m_vert[i].m2,
(u8vec4)(m_vert[i].m3 * 255.f));
#endif

Array<uint16_t> indexlist;
for (int i = 0; i < m_indices.Count(); i += 3)
@@ -135,6 +167,7 @@ void EasyMesh::MeshConvert(Shader* provided_shader)
m_gpu.indexcount = indexlist.Count();
}

//-----------------------------------------------------------------------------
void EasyMesh::Render(mat4 const &model, float damage)
{
DebugRenderMode d = Video::GetDebugRenderMode();
@@ -155,13 +188,22 @@ void EasyMesh::Render(mat4 const &model, float damage)
m_gpu.shader[d]->SetUniform(m_gpu.lights[d], light_data);

m_gpu.shader[d]->SetUniform(m_gpu.modelview[d], modelview);
m_gpu.shader[d]->SetUniform(m_gpu.invmodelview[d], inverse(modelview));
m_gpu.shader[d]->SetUniform(m_gpu.view[d], Scene::GetDefault()->GetViewMatrix());
m_gpu.shader[d]->SetUniform(m_gpu.invview[d], inverse(Scene::GetDefault()->GetViewMatrix()));
m_gpu.shader[d]->SetUniform(m_gpu.proj[d], Scene::GetDefault()->GetProjMatrix());
m_gpu.shader[d]->SetUniform(m_gpu.normalmat[d], normalmat);
m_gpu.shader[d]->SetUniform(m_gpu.damage[d], damage);
m_gpu.vdecl->Bind();
#if VERTEX_USEAGE == VU_BONES
//TODO : -- BONE SUPPORT --
#elif VERTEX_USEAGE == VU_TEX_UV
//UV SUPPORT --
m_gpu.vdecl->SetStream(m_gpu.vbo, m_gpu.coord[d], m_gpu.norm[d], m_gpu.color[d], m_gpu.tex_coord[d]);
#else
//-- VANILLA --
m_gpu.vdecl->SetStream(m_gpu.vbo, m_gpu.coord[d], m_gpu.norm[d], m_gpu.color[d]);
#endif
m_gpu.ibo->Bind();
m_gpu.vdecl->DrawIndexedElements(MeshPrimitive::Triangles,
0, 0, m_gpu.vertexcount,
@@ -170,60 +212,162 @@ 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)
int VertexDictionnary::FindVertexMaster(const int search_idx)
{
//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;
for (int j = 0; j < vertex_list.Count(); j++)
if (vertex_list[j].m1 == search_idx)
return vertex_list[j].m3;
return VDictType::DoesNotExist;
}

//helpers func to retrieve a triangle.
int FindTriangleInDict(int search_idx, Array< int, Array< vec3, vec3, vec3 > > const &triangle_isec)
//-----------------------------------------------------------------------------
//retrieve a list of matching vertices, doesn't include search_idx.
bool VertexDictionnary::FindMatchingVertices(const int search_idx, Array<int> &matching_ids)
{
//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;
int cur_mast = FindVertexMaster(search_idx);

if (cur_mast == VDictType::DoesNotExist || cur_mast == VDictType::Alone)
return false;

if (cur_mast == VDictType::Master)
cur_mast = search_idx;
else
matching_ids << vertex_list[cur_mast].m1;

for (int j = 0; j < vertex_list.Count(); j++)
if (vertex_list[j].m3 == cur_mast && vertex_list[j].m1 != search_idx)
matching_ids << vertex_list[cur_mast].m1;

return (matching_ids.Count() > 0);
}

//-----------------------------------------------------------------------------
//Will return connected vertices (through triangles), if returned vertex has matching ones, it only returns the master.
bool VertexDictionnary::FindConnectedVertices(const int search_idx, const Array<int> &tri_list, Array<int> &connected_vert, Array<int> const *ignored_tri)
{
Array<int> connected_tri;
FindConnectedTriangles(search_idx, tri_list, connected_tri, ignored_tri);

for (int i = 0; i < connected_tri.Count(); i++)
{
for (int j = 0; j < 3; j++)
{
int v_indice = tri_list[connected_tri[j] + j];
if (v_indice != search_idx)
{
int found_master = FindVertexMaster(tri_list[connected_tri[j] + j]);
if (found_master == VDictType::Alone || found_master == VDictType::Master)
connected_vert << v_indice;
else
connected_vert << found_master;
}
}
}
return (connected_vert.Count() > 0);
}
//-----------------------------------------------------------------------------
bool VertexDictionnary::FindConnectedTriangles(const int search_idx, const Array<int> &tri_list, Array<int> &connected_tri, Array<int> const *ignored_tri)
{
return FindConnectedTriangles(ivec3(search_idx, search_idx, search_idx), tri_list, connected_tri, ignored_tri);
}
//-----------------------------------------------------------------------------
bool VertexDictionnary::FindConnectedTriangles(const ivec2 &search_idx, const Array<int> &tri_list, Array<int> &connected_tri, Array<int> const *ignored_tri)
{
return FindConnectedTriangles(ivec3(search_idx, search_idx.x), tri_list, connected_tri, ignored_tri);
}
//-----------------------------------------------------------------------------
bool VertexDictionnary::FindConnectedTriangles(const ivec3 &search_idx, const Array<int> &tri_list, Array<int> &connected_tri, Array<int> const *ignored_tri)
{
int needed_validation = 0;
Array<int> vert_list[3];
for (int i = 0; i < 3; i++)
{
//Small optim since above func will use this one
if ((i == 1 && search_idx[0] == search_idx[1]) ||
(i == 2 && (search_idx[0] == search_idx[2] || search_idx[1] == search_idx[2])))
continue;
else
{
//increment the validation info, hence empty list aren't taken into account.
needed_validation++;
vert_list[i] << search_idx[i];
FindMatchingVertices(search_idx[i], vert_list[i]);
}
}

for (int i = 0; i < tri_list.Count(); i += 3)
{
if (ignored_tri)
{
bool should_pass = false;
for (int j = 0; !should_pass && j < ignored_tri->Count(); j++)
if ((*ignored_tri)[j] == i)
should_pass = true;
if (should_pass)
continue;
}
int found_validation = 0;
for (int j = 0; j < 3; j++)
{
bool validated = false;
for (int k = 0; !validated && k < vert_list[j].Count(); k++)
for (int l = 0; !validated && l < 3; l++)
if (vert_list[j][k] == tri_list[i + l])
validated = true;
found_validation += (validated)?(1):(0);
}
//triangle is validated store it
if (found_validation == needed_validation)
connected_tri << i;
}

return (connected_tri.Count() > 0);
}

//-----------------------------------------------------------------------------
//Will update the given list with all the vertices on the same spot.
void EasyMesh::UpdateVertexDict(Array< int, int > &vertex_dict)
void VertexDictionnary::AddVertex(const int vert_id, const vec3 vert_coord)
{
for (int j = 0; j < vertex_list.Count(); j++)
if (vertex_list[j].m1 == vert_id)
return;

//First, build the vertex Dictionnary
for (int i = 0; i < m_vert.Count(); i++)
int i = 0;
for (; i < master_list.Count(); i++)
{
int CurIdx = FindVertexInDict(i, vertex_dict);
int cur_mast = master_list[i];
int cur_id = vertex_list[cur_mast].m1;
vec3 cur_loc = vertex_list[cur_mast].m2;
int &cur_type = vertex_list[cur_mast].m3;

//go through all vertices and do the match-up.
if (CurIdx == -1)
if (cur_id == vert_id)
return;

if (sqlength(cur_loc - vert_coord) < CSG_EPSILON)
{
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);
}
}
if (cur_type == VDictType::Alone)
cur_type = VDictType::Master;
vertex_list.Push(vert_id, vert_coord, cur_mast);
return;
}
}

//We're here because we couldn't find any matching vertex
master_list.Push(vertex_list.Count());
vertex_list.Push(vert_id, vert_coord, VDictType::Alone);
}

//-----------------------------------------------------------------------------
void EasyMesh::MeshCsg(CSGUsage csg_operation)
{
//A vertex dictionnary for vertices on the same spot.
@@ -399,206 +543,50 @@ void EasyMesh::MeshCsg(CSGUsage csg_operation)
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;
}

//-----------------------------------------------------------------------------
void EasyMesh::SetCurColor(vec4 const &color)
{
m_color = color;
}

//-----------------------------------------------------------------------------
void EasyMesh::SetCurColor2(vec4 const &color)
{
m_color2 = 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));
#if VERTEX_USEAGE == VU_BONES
//TODO : -- BONE SUPPORT --
m_vert.Push(coord, vec3(0.f, 1.f, 0.f), m_color, ivec2(0), vec2(0));
#elif VERTEX_USEAGE == VU_TEX_UV
//-- UV SUPPORT --
m_vert.Push(coord, vec3(0.f, 1.f, 0.f), m_color, vec2(-1));
#else
//-- VANILLA --
m_vert.Push(coord, vec3(0.f, 1.f, 0.f), m_color);
#endif
}

//-----------------------------------------------------------------------------
void EasyMesh::AddDuplicateVertex(int i)
{
m_vert << m_vert[i];
}

//-----------------------------------------------------------------------------
void EasyMesh::AppendQuad(int i1, int i2, int i3, int i4, int base)
{
m_indices << base + i1;
@@ -610,6 +598,7 @@ void EasyMesh::AppendQuad(int i1, int i2, int i3, int i4, int base)
m_indices << base + i3;
}

//-----------------------------------------------------------------------------
void EasyMesh::AppendQuadDuplicateVerts(int i1, int i2, int i3, int i4, int base)
{
m_indices << m_vert.Count(); AddDuplicateVertex(base + i1);
@@ -621,6 +610,7 @@ void EasyMesh::AppendQuadDuplicateVerts(int i1, int i2, int i3, int i4, int base
m_indices << m_vert.Count(); AddDuplicateVertex(base + i3);
}

//-----------------------------------------------------------------------------
void EasyMesh::AppendTriangle(int i1, int i2, int i3, int base)
{
m_indices << base + i1;
@@ -628,6 +618,7 @@ void EasyMesh::AppendTriangle(int i1, int i2, int i3, int base)
m_indices << base + i3;
}

//-----------------------------------------------------------------------------
void EasyMesh::AppendTriangleDuplicateVerts(int i1, int i2, int i3, int base)
{
m_indices << m_vert.Count(); AddDuplicateVertex(base + i1);
@@ -635,6 +626,7 @@ void EasyMesh::AppendTriangleDuplicateVerts(int i1, int i2, int i3, int base)
m_indices << m_vert.Count(); AddDuplicateVertex(base + i3);
}

//-----------------------------------------------------------------------------
void EasyMesh::ComputeNormals(int start, int vcount)
{
for (int i = 0; i < vcount; i += 3)
@@ -650,32 +642,209 @@ void EasyMesh::ComputeNormals(int start, int vcount)
}
}

//-----------------------------------------------------------------------------
void EasyMesh::ComputeTexCoord(float uv_scale, int uv_offset)
{
#if VERTEX_USEAGE == VU_TEX_UV
VertexDictionnary vert_dict;
Array<int> tri_list;
tri_list.Reserve(m_indices.Count() - m_cursors.Last().m2);
for (int i = m_cursors.Last().m2; i < m_indices.Count(); i++)
{
vert_dict.AddVertex(m_indices[i], m_vert[m_indices[i]].m1);
tri_list << m_indices[i];
}

//full triangle count
Array<int> tri_done;
Array<int> tri_check;
int tri_count = (m_indices.Count() - m_cursors.Last().m2) / 3;

tri_check << tri_list[0];

while (tri_check.Count())
{
int cur_tri = tri_check[0];
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] };
vec2 uv[3] = { m_vert[tri_list[cur_tri]].m4, m_vert[tri_list[cur_tri + 1]].m4, m_vert[tri_list[cur_tri + 2]].m4 };
for (int j = 0; j < 3; j++)
{
if (uv[j] != vec2(-1.0f) && uv[j] == uv[(j + 1) % 3])
{
uv[0] = vec2(-1.0f);
uv[1] = vec2(-1.0f);
uv[2] = vec2(-1.0f);
break;
}
}
int uv_set = 0;
for (int j = 0; j < 3; j++)
uv_set += (uv[j].x < 0.f)?(0):(1);

//this case shouldn't happen.
if (uv_set == 1)
{
/*
for (int j = 0; j < 3; j++)
{
if (uv[j] != vec2(-1.0f))
{
uv[(j + 1) % 2] = uv[j] + vec2(.0f, uv_scale * length(m_vert[v[j]].m1 - m_vert[v[(j + 1) % 3]].m1));
uv_set = 2;
break;
}
}
*/
}
//No UV is set, let's do the arbitrary set and use the basic method.
if (uv_set == 0)
{
float new_dot = FLT_MAX;
int base_i = 0;
for (int j = 0; j < 3; j++)
{
float tmp_dot = abs(dot(normalize(m_vert[v[(j + 1) % 3]].m1 - m_vert[v[j]].m1),
normalize(m_vert[v[(j + 2) % 3]].m1 - m_vert[v[j]].m1)));
if (tmp_dot < new_dot)
{
base_i = j;
new_dot = tmp_dot;
}
}
uv[base_i] = vec2(.0f);
uv[(base_i + 1) % 3] = vec2(.0f, uv_scale * length(m_vert[v[base_i]].m1 - m_vert[v[(base_i + 1) % 3]].m1));
uv_set = 2;
}
//2 points have been set, let's figure the third
if (uv_set == 2)
{
{
//invert values so the two set uv are in [0, 1] slots.
int new_v[3];
vec2 new_uv[3];
bool ignore_set = false;
if (uv[0].x >= 0.f && uv[1].x < 0.f)
{
new_v[0] = v[2]; new_v[1] = v[0]; new_v[2] = v[1];
new_uv[0] = uv[2]; new_uv[1] = uv[0]; new_uv[2] = uv[1];
}
else if (uv[0].x < 0.f && uv[1].x >= 0.f)
{
new_v[0] = v[1]; new_v[1] = v[2]; new_v[2] = v[0];
new_uv[0] = uv[1]; new_uv[1] = uv[2]; new_uv[2] = uv[0];
}
else
ignore_set = true;
if (!ignore_set)
{
v[0] = new_v[0]; v[1] = new_v[1]; v[2] = new_v[2];
uv[0] = new_uv[0]; uv[1] = new_uv[1]; uv[2] = new_uv[2];
}
}

//Do this to be sure the normal is OK.
ComputeNormals(cur_tri, 3);
vec3 v01 = normalize(m_vert[v[1]].m1 - m_vert[v[0]].m1);
vec3 v02 = m_vert[v[2]].m1 - m_vert[v[0]].m1;
vec3 v_dir = normalize(cross(m_vert[m_indices[cur_tri]].m2, v01));
vec2 texu_dir = uv[1] - uv[0];
vec2 texv_dir = vec2(texu_dir.y, -texu_dir.x);
//Final calculations
uv[2] = texu_dir * dot(v01, v02) + texv_dir * dot(v_dir, v02);

//Set UV on ALL matching vertices!
Array<int> matching_vert;
for (int i = 0; i < 3; i++)
{
#if 1
//This marks all same position UV to the same values
//Deactivation is a test.
matching_vert << v[i];
vert_dict.FindMatchingVertices(v[i], matching_vert);
for (int j = 0; j < matching_vert.Count(); j++)
if (m_vert[matching_vert[j]].m4 == vec2(-1.0f))
m_vert[matching_vert[j]].m4 = abs(uv[i]);
#else
m_vert[v[i]].m4 = abs(uv[i]);
#endif
}

tri_done << cur_tri;
tri_check.Remove(0);

//Get connected triangles and go from there.
for (int j = 0; j < 3; j++)
{
#if 0
//This finds triangle that are connected to this triangle
vert_dict.FindConnectedTriangles(ivec2(v[j], v[(j + 1) % 3]), tri_list, tri_check, &tri_done);
#else
//This finds triangle that are connected to the vertices of this triangle
vert_dict.FindConnectedTriangles(v[j], tri_list, tri_check, &tri_done);
#endif
}
}
else if (uv_set == 3)
{
bool tri_present = false;
for (int j = 0; j < tri_done.Count(); j++)
if (cur_tri == tri_done[j])
tri_present = true;
if (!tri_present)
tri_done << cur_tri;
tri_check.Remove(0);
}

if (tri_check.Count() == 0 && tri_done.Count() != tri_count)
{
//look for unset triangle
for (int i = 0; !tri_check.Count() && i < tri_list.Count(); i += 3)
{
bool tri_present = false;
for (int j = 0; j < tri_done.Count(); j++)
if (i == tri_done[j])
tri_present = true;
if (!tri_present)
tri_check << i;
}
}
}
#endif
}

//-----------------------------------------------------------------------------
void EasyMesh::SetVertColor(vec4 const &color)
{
for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
m_vert[i].m3 = color;
}

//-----------------------------------------------------------------------------
void EasyMesh::SetCurVertNormal(vec3 const &normal)
{
m_vert[m_vert.Count() - 1].m2 = normal;
}

//-----------------------------------------------------------------------------
void EasyMesh::SetCurVertColor(vec4 const &color)
{
m_vert[m_vert.Count() - 1].m3 = color;
}

//-----------------------------------------------------------------------------
void EasyMesh::Translate(vec3 const &v)
{
for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
m_vert[i].m1 += v;
}

//-----------------------------------------------------------------------------
void EasyMesh::RotateX(float t) { Rotate(t, vec3(1, 0, 0)); }
void EasyMesh::RotateY(float t) { Rotate(t, vec3(0, 1, 0)); }
void EasyMesh::RotateZ(float t) { Rotate(t, vec3(0, 0, 1)); }

//-----------------------------------------------------------------------------
void EasyMesh::Rotate(float t, vec3 const &axis)
{
mat3 m = mat3::rotate(t, axis);
@@ -686,6 +855,7 @@ void EasyMesh::Rotate(float t, vec3 const &axis)
}
}

//-----------------------------------------------------------------------------
void EasyMesh::RadialJitter(float r)
{
Array<int> Welded;
@@ -730,6 +900,7 @@ void EasyMesh::RadialJitter(float r)
ComputeNormals(m_cursors.Last().m2, m_indices.Count() - m_cursors.Last().m2);
}

//-----------------------------------------------------------------------------
void EasyMesh::TaperX(float y, float z, float xoff)
{
/* FIXME: this code breaks normals! */
@@ -740,6 +911,7 @@ void EasyMesh::TaperX(float y, float z, float xoff)
}
}

//-----------------------------------------------------------------------------
void EasyMesh::TaperY(float x, float z, float yoff)
{
for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
@@ -749,6 +921,7 @@ void EasyMesh::TaperY(float x, float z, float yoff)
}
}

//-----------------------------------------------------------------------------
void EasyMesh::TaperZ(float x, float y, float zoff)
{
for (int i = m_cursors.Last().m1; i < m_vert.Count(); i++)
@@ -758,6 +931,7 @@ void EasyMesh::TaperZ(float x, float y, float zoff)
}
}

//-----------------------------------------------------------------------------
void EasyMesh::Scale(vec3 const &s)
{
vec3 const invs = vec3(1) / s;
@@ -780,10 +954,12 @@ void EasyMesh::Scale(vec3 const &s)
}
}

//-----------------------------------------------------------------------------
void EasyMesh::MirrorX() { DupAndScale(vec3(-1, 1, 1)); }
void EasyMesh::MirrorY() { DupAndScale(vec3(1, -1, 1)); }
void EasyMesh::MirrorZ() { DupAndScale(vec3(1, 1, -1)); }

//-----------------------------------------------------------------------------
void EasyMesh::DupAndScale(vec3 const &s)
{
int vlen = m_vert.Count() - m_cursors.Last().m1;
@@ -801,6 +977,7 @@ void EasyMesh::DupAndScale(vec3 const &s)
m_cursors.Last().m2 -= tlen;
}

//-----------------------------------------------------------------------------
void EasyMesh::AppendCylinder(int nsides, float h, float r1, float r2,
int dualside, int smooth)
{
@@ -853,6 +1030,7 @@ void EasyMesh::AppendCylinder(int nsides, float h, float r1, float r2,
}
}

//-----------------------------------------------------------------------------
void EasyMesh::AppendCapsule(int ndivisions, float h, float r)
{
int ibase = m_indices.Count();
@@ -949,6 +1127,7 @@ void EasyMesh::AppendCapsule(int ndivisions, float h, float r)
ComputeNormals(ibase, m_indices.Count() - ibase);
}

//-----------------------------------------------------------------------------
void EasyMesh::AppendSphere(int ndivisions, vec3 const &size)
{
OpenBrace();
@@ -957,6 +1136,7 @@ void EasyMesh::AppendSphere(int ndivisions, vec3 const &size)
CloseBrace();
}

//-----------------------------------------------------------------------------
void EasyMesh::AppendTorus(int ndivisions, float r1, float r2)
{
int ibase = m_indices.Count();
@@ -990,21 +1170,25 @@ void EasyMesh::AppendTorus(int ndivisions, float r1, float r2)
ComputeNormals(ibase, m_indices.Count() - ibase);
}

//-----------------------------------------------------------------------------
void EasyMesh::AppendBox(vec3 const &size, float chamf)
{
AppendBox(size, chamf, false);
}

//-----------------------------------------------------------------------------
void EasyMesh::AppendSmoothChamfBox(vec3 const &size, float chamf)
{
AppendBox(size, chamf, true);
}

//-----------------------------------------------------------------------------
void EasyMesh::AppendFlatChamfBox(vec3 const &size, float chamf)
{
AppendBox(size, chamf, false);
}

//-----------------------------------------------------------------------------
void EasyMesh::AppendBox(vec3 const &size, float chamf, bool smooth)
{
if (chamf < 0.0f)
@@ -1100,6 +1284,7 @@ void EasyMesh::AppendBox(vec3 const &size, float chamf, bool smooth)
ComputeNormals(ibase, m_indices.Count() - ibase);
}

//-----------------------------------------------------------------------------
void EasyMesh::AppendStar(int nbranches, float r1, float r2,
int fade, int fade2)
{
@@ -1131,6 +1316,7 @@ void EasyMesh::AppendStar(int nbranches, float r1, float r2,
}
}

//-----------------------------------------------------------------------------
void EasyMesh::AppendExpandedStar(int nbranches, float r1,
float r2, float extrar)
{
@@ -1165,6 +1351,7 @@ void EasyMesh::AppendExpandedStar(int nbranches, float r1,
}
}

//-----------------------------------------------------------------------------
void EasyMesh::AppendDisc(int nsides, float r, int fade)
{
int vbase = m_vert.Count();
@@ -1184,6 +1371,7 @@ void EasyMesh::AppendDisc(int nsides, float r, int fade)
}
}

//-----------------------------------------------------------------------------
void EasyMesh::AppendSimpleTriangle(float size, int fade)
{
mat3 m = mat3::rotate(120.f, 0.f, 1.f, 0.f);
@@ -1202,11 +1390,13 @@ void EasyMesh::AppendSimpleTriangle(float size, int fade)
AppendTriangle(0, 1, 2, m_vert.Count() - 3);
}

//-----------------------------------------------------------------------------
void EasyMesh::AppendSimpleQuad(float size, int fade)
{
AppendSimpleQuad(vec2(size * .5f), vec2(size * -.5f), 0.f, fade);
}

//-----------------------------------------------------------------------------
void EasyMesh::AppendSimpleQuad(vec2 p1, vec2 p2, float z, int fade)
{
AddVertex(vec3(p2.x, z, -p1.y));
@@ -1222,6 +1412,7 @@ void EasyMesh::AppendSimpleQuad(vec2 p1, vec2 p2, float z, int fade)
ComputeNormals(m_indices.Count() - 6, 6);
}

//-----------------------------------------------------------------------------
void EasyMesh::AppendCog(int nbsides, float h, float r10, float r20,
float r1, float r2, float r12, float r22,
float sidemul, int offset)
@@ -1297,6 +1488,7 @@ void EasyMesh::AppendCog(int nbsides, float h, float r10, float r20,
ComputeNormals(ibase, m_indices.Count() - ibase);
}

//-----------------------------------------------------------------------------
void EasyMesh::Chamfer(float f)
{
int vlen = m_vert.Count() - m_cursors.Last().m1;
@@ -1320,6 +1512,7 @@ void EasyMesh::Chamfer(float f)
vertices[m_indices[i]]++;

for (int i = 0; i < ilen / 3; i++)

{
#if 0
if (vertices[m_indices[i * 3]] > 1)


+ 64
- 4
src/easymesh/easymesh.h View File

@@ -15,6 +15,12 @@
// ------------------
//

#define VU_BONES 2
#define VU_TEX_UV 1
#define VU_VANILLA 0

#define VERTEX_USEAGE VU_VANILLA

#if !defined __EASYMESH_EASYMESH_H__
#define __EASYMESH_EASYMESH_H__

@@ -38,6 +44,39 @@ struct CSGUsage
inline operator Value() { return m_value; }
};

/* A safe enum for VertexDictionnary operations. */
struct VDictType
{
enum Value
{
DoesNotExist=-3,
Alone=-2,
Master=-1
}
m_value;

inline VDictType(Value v) : m_value(v) {}
inline operator Value() { return m_value; }
};

//a class whose goal is to keep a list of the adjacent vertices for mesh operations purposes
class VertexDictionnary
{
public:
int FindVertexMaster(const int search_idx);
bool FindMatchingVertices(const int search_idx, Array<int> &matching_ids);
bool FindConnectedVertices(const int search_idx, const Array<int> &tri_list, Array<int> &connected_vert, Array<int> const *ignored_tri = NULL);
bool FindConnectedTriangles(const int search_idx, const Array<int> &tri_list, Array<int> &connected_tri, Array<int> const *ignored_tri = NULL);
bool FindConnectedTriangles(const ivec2 &search_idx, const Array<int> &tri_list, Array<int> &connected_tri, Array<int> const *ignored_tri = NULL);
bool FindConnectedTriangles(const ivec3 &search_idx, const Array<int> &tri_list, Array<int> &connected_tri, Array<int> const *ignored_tri = NULL);
void AddVertex(int vert_id, vec3 vert_coord);
void Clear() { vertex_list.Empty(); }
private:
//<VertexId, VertexLocation, VertexMasterId>
Array<int, vec3, int> vertex_list;
//List of the master_ vertices
Array<int> master_list;
};

class EasyMesh
{
@@ -81,6 +120,8 @@ private:
void AppendTriangle(int i1, int i2, int i3, int base);
void AppendTriangleDuplicateVerts(int i1, int i2, int i3, int base);
void ComputeNormals(int start, int vcount);
public:
void ComputeTexCoord(float uv_scale, int uv_offset);
void SetVertColor(vec4 const &color);

void SetCurVertNormal(vec3 const &normal);
@@ -141,11 +182,21 @@ 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;
#if VERTEX_USEAGE == VU_BONES
//TODO : -- BONE SUPPORT --
//TODO : <COORD, NORM, COLOR, BONE_ID, BONE_WEIGHT>
Array<vec3, vec3, vec4, ivec2, vec2> m_vert;
//TODO : More bone blend support than 2 ?
//<coord, norm, color>
#elif VERTEX_USEAGE == VU_TEX_UV
//TODO : -- UV SUPPORT --
//TODO : <COORD, NORM, COLOR, UV>
Array<vec3, vec3, vec4, vec2> m_vert;
#else
//-- VANILLA --
//<COORD, NORM, COLOR>
Array<vec3, vec3, vec4> m_vert;
#endif

//<vert count, indices count>
Array<int, int> m_cursors;
//When this flag is up, negative scaling will not invert faces.
@@ -156,8 +207,17 @@ private:
{
/* FIXME: very naughty way of handling debug render modes */
Array<Shader *>shader;
#if VERTEX_USEAGE == VU_BONES
//TODO : -- BONE SUPPORT --
Array<ShaderAttrib> coord, norm, color, bone_id, bone_weight;
#elif VERTEX_USEAGE == VU_TEX_UV
//-- UV SUPPORT --
Array<ShaderAttrib> coord, norm, color, tex_coord;
#else
//-- VANILLA --
Array<ShaderAttrib> coord, norm, color;
Array<ShaderUniform> modelview, view, invview, proj, normalmat, damage, lights;
#endif
Array<ShaderUniform> modelview, invmodelview, view, invview, proj, normalmat, damage, lights;

VertexDeclaration *vdecl;
VertexBuffer *vbo;


+ 6
- 0
src/easymesh/shiny.lolfx View File

@@ -45,6 +45,12 @@ varying vec3 pass_TNormal;
varying vec4 pass_Color;

#if 0
//Cos(45) = 0.70710678118
//1.0 - Cos(45) = 0.29289321881

const float cos_45 = 0.70710678118;
const float inv_cos_45 = 0.29289321881;

//Cube Light
vec4 in_Light3_Pos = vec4(-10.0, 10.0, 5.0, 1.0);
vec3 in_Light3_Size_Inner = vec3(3.0, 1.0, 3.0);


+ 5
- 76
src/easymesh/shinydebugUV.lolfx View File

@@ -5,6 +5,7 @@
attribute vec3 in_Vertex;
attribute vec3 in_Normal;
attribute vec4 in_Color;
attribute vec2 in_TexCoord;

uniform mat4 in_ModelView;
uniform mat4 in_View;
@@ -14,6 +15,7 @@ uniform mat3 in_NormalMat;
varying vec4 pass_Vertex; /* View space */
varying vec3 pass_TNormal;
varying vec4 pass_Color;
varying vec2 pass_TexCoord;

void main(void)
{
@@ -23,6 +25,7 @@ void main(void)
pass_Vertex = vertex;
pass_TNormal = tnorm;
pass_Color = in_Color;
pass_TexCoord = in_TexCoord;

gl_Position = in_Proj * vertex;
}
@@ -43,85 +46,11 @@ uniform vec4 u_Lights[8 * 2];
varying vec4 pass_Vertex; /* View space */
varying vec3 pass_TNormal;
varying vec4 pass_Color;

#if 0
//Cube Light
vec4 in_Light3_Pos = vec4(-10.0, 10.0, 5.0, 1.0);
vec3 in_Light3_Size_Inner = vec3(3.0, 1.0, 3.0);
vec3 in_Light3_Size_Outer = vec3(15.0, 15.0, 15.0);
vec3 in_Light3_diffuse = vec3(0.4, 1.0, 0.4);
#endif
varying vec2 pass_TexCoord;

void main(void)
{
/* Material properties */
vec3 specular_reflect = vec3(0.8, 0.75, 0.4);
float specular_power = 60.0;

/* World properties */
vec3 ambient = vec3(0.1, 0.1, 0.1);
vec3 specular = vec3(0.0, 0.0, 0.0);
vec3 diffuse = vec3(0.0, 0.0, 0.0);

/* Light precalculations */
vec3 v = normalize(-pass_Vertex.xyz);

/* Apply lighting */
for (int i = 0; i < 8; i++)
{
vec4 pos = u_Lights[i * 2];
vec4 color = u_Lights[i * 2 + 1];
vec3 s, r;

if (pos.w > 0.0)
{
/* Point light -- no attenuation yet */
s = normalize((in_View * pos).xyz - pass_Vertex.xyz);
r = reflect(-s, pass_TNormal);
}
else
{
/* Directional light */
s = normalize(-pos.xyz);
r = reflect(s, pass_TNormal);
}

float sdotn = max(dot(s, pass_TNormal), 0.0);
diffuse += color.xyz * sdotn;
if (sdotn > 0.0)
specular += color.xyz * specular_reflect
* pow(max(dot(r, v), 0.0), specular_power);
}

#if 0
//Light calculation for cube light
vec3 specular_color = vec3(1.0, 1.0, 0.6);
vec3 Local_Vertex = (in_Inv_View * pass_Vertex).xyz - (in_Light3_Pos).xyz;
vec3 Proj_Vertex = clamp(Local_Vertex.xyz, -in_Light3_Size_Inner, in_Light3_Size_Inner);
vec3 new_LightDir = Local_Vertex - Proj_Vertex;

vec3 light_radius = max(vec3(0.0,0.0,0.0), vec3(1.0,1.0,1.0) - abs(new_LightDir / in_Light3_Size_Outer));
float light_radius_mod = min(light_radius.x, min(light_radius.y, light_radius.z));

if (length(new_LightDir) == 0.0)
sdotn = 1.0;
else
{
new_LightDir = normalize((in_View * vec4(Proj_Vertex + in_Light3_Pos.xyz,1.0)).xyz - pass_Vertex.xyz);
sdotn = max(dot(new_LightDir, pass_TNormal), 0.0);
r = reflect(-new_LightDir, pass_TNormal);
if (sdotn > 0.0 && light_radius_mod > 0.0)
specular += specular_color * min(specular_reflect, light_radius_mod)
* pow(max(dot(r, v), 0.0), specular_power);
}
diffuse += in_Light3_diffuse * min(sdotn, light_radius_mod);
//----------
#endif

vec3 light = ambient + diffuse + specular;

vec4 real_color = mix(pass_Color, vec4(1.2, 1.2, 1.2, 1.0), in_Damage);
gl_FragColor = real_color * vec4(light, 1.0);
gl_FragColor = vec4(mod(pass_TexCoord.x, 1.0f), 0.2, mod(pass_TexCoord.y, 1.0), 1.0) * length(normalize(pass_Color.xyz)) * length(normalize(pass_TNormal));
}

[vert.hlsl]


+ 5
- 2
src/video.cpp View File

@@ -254,14 +254,17 @@ void Video::SetDebugRenderMode(DebugRenderMode d)
#elif defined HAVE_GLES_2X
glEnable(GL_CULL_FACE);
#else
glEnable(GL_CULL_FACE);
if (VideoData::render_mode == d && glIsEnabled(GL_CULL_FACE) == GL_TRUE)
glDisable(GL_CULL_FACE);
else
glEnable(GL_CULL_FACE);
glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
#endif
break;
}
case DebugRenderMode::Wireframe:
{
if (VideoData::render_mode == DebugRenderMode::Wireframe)
if (VideoData::render_mode == d)
{
#if defined USE_D3D9 || defined _XBOX
#else


+ 36
- 1
test/MeshViewer.cpp View File

@@ -21,6 +21,8 @@
using namespace std;
using namespace lol;

LOLFX_RESOURCE_DECLARE(shinyfur);

#define IPT_CAM_RESET "Cam_Center"
#define IPT_CAM_FORWARD "Cam_Forward"
#define IPT_CAM_BACKWARD "Cam_Backward"
@@ -43,6 +45,8 @@ using namespace lol;
#define IPT_MESH_ROT_UP "Mesh_Rot_Up"
#define IPT_MESH_ROT_DOWN "Mesh_Rot_Down"

#define WITH_FUR 0

class MeshViewer : public WorldEntity
{
public:
@@ -270,6 +274,24 @@ public:
String cmd = f.ReadString();
f.Close();

for (int i = 0; i < cmd.Count() - 1; i++)
{
if (cmd[i] == '/' && cmd[i + 1] == '/')
{
int j = i;
for (; j < cmd.Count(); j++)
{
if (cmd[j] == '\r' || cmd[j] == '\n')
break;
}
String new_cmd = cmd.Sub(0, i);
if (j < cmd.Count())
new_cmd += cmd.Sub(j, cmd.Count() - j);
cmd = new_cmd;
i--;
}
}

if (cmd.Count()
&& (!m_cmdlist.Count() || cmd != m_cmdlist.Last()))
{
@@ -277,7 +299,10 @@ public:

//Create a new mesh
m_meshes.Push(EasyMesh(), false, .0f, vec3(.0f));
m_meshes.Last().m1.Compile(cmd.C());
if (!m_meshes.Last().m1.Compile(cmd.C()))
m_meshes.Pop();
else
m_meshes.Last().m1.ComputeTexCoord(0.2f, 2);
}
}
}
@@ -304,7 +329,12 @@ public:
{
if (!m_meshes[i].m2)
{
//Fur support
#if WITH_FUR
m_meshes[i].m1.MeshConvert(Shader::Create(LOLFX_RESOURCE_NAME(shinyfur)));
#else
m_meshes[i].m1.MeshConvert();
#endif
m_meshes[i].m2 = true;
}
}
@@ -330,7 +360,12 @@ public:
mat4::scale(vec3(vec2(m_meshes[i].m3), 1.0f)) *
default_proj *
m_fov_compensation);
#if WITH_FUR
for (int j=0; j < 40; j++)
m_meshes[i].m1.Render(m_mat, 0.1 * j);
#else
m_meshes[i].m1.Render(m_mat);
#endif
Video::Clear(ClearMask::Depth);
}
}


+ 3
- 0
test/MeshViewer.vcxproj View File

@@ -47,6 +47,9 @@
<ExcludedFromBuild Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">true</ExcludedFromBuild>
</None>
</ItemGroup>
<ItemGroup>
<LolFxCompile Include="shinyfur.lolfx" />
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{7CE9FE12-E4AB-4A22-90D4-2C15F0C30D4E}</ProjectGuid>
<ConfigurationType>Application</ConfigurationType>


+ 11
- 1
test/MeshViewerBuffer.txt View File

@@ -1 +1,11 @@
[sc#2f2 ab 2 2 2 t .8 .8 .8 rx 20 ry 20 [sc#22f ab 2 2 2 tx 0 csgu]]
[sc#88f ab 4 4 4]
//[sc#ff2 asph 2 4 4 4]
//[sc#ff2 acap 2 4 4]
//[sc#ff2 ac 12 4 4 4 0 0]
//[sc#ff2 asph 2 10 10 10]
//[sc#400 asph 2 10 10 10 t 2 2 2 csgs]
//[sc#88f afcb 10 10 10 .25 tx 0 sc 0.1]
//[sc#22f afcb 10 10 10 .25 t 2 2 2 csgs]
//[sc#fff afcb 7 7 7 .25]
//[sc#ff2 afcb 7 7 7 .25 t 1 1 1]

+ 183
- 0
test/shinyfur.lolfx View File

@@ -0,0 +1,183 @@

[vert.glsl]
#version 120

attribute vec3 in_Vertex;
attribute vec3 in_Normal;
attribute vec4 in_Color;

uniform mat4 in_ModelView;
uniform mat4 in_View;
uniform mat4 in_Proj;
uniform mat3 in_NormalMat;
uniform float in_Damage;

varying vec4 pass_Vertex; /* View space */
varying vec3 pass_TNormal;
varying vec4 pass_Color;

void main(void)
{
vec4 vertex = vec4(in_Vertex + (in_Normal * in_Damage), 1.0);
float dam_perc = in_Damage / (0.1 * 40);
vec3 vGravity = vec3(0.0, -0.981, 0.0) * 2.0;
float k = pow(dam_perc, 3);
vertex = in_ModelView * vertex + in_View * vec4(vGravity * k, 1.0);
vec3 tnorm = normalize(in_NormalMat * in_Normal);

pass_Vertex = vertex;
pass_TNormal = tnorm;
pass_Color = in_Color;

gl_Position = in_Proj * vertex;
}

[frag.glsl]
#version 120

#if defined GL_ES
precision highp float;
#endif

uniform mat4 in_View;
uniform mat4 in_Inv_View;
uniform mat4 in_Inv_ModelView;
uniform float in_Damage;

//Light list
uniform vec4 u_Lights[8 * 2];

varying vec4 pass_Vertex; /* View space */
varying vec3 pass_TNormal;
varying vec4 pass_Color;

void main(void)
{
/* Material properties */
vec3 specular_reflect = vec3(0.8, 0.75, 0.4);
float specular_power = 60.0;

/* World properties */
vec3 ambient = vec3(0.7, 0.7, 0.7);
vec3 specular = vec3(0.0, 0.0, 0.0);
vec3 diffuse = vec3(0.0, 0.0, 0.0);

/* Light precalculations */
vec3 v = normalize(-pass_Vertex.xyz);

/* Apply lighting */
for (int i = 0; i < 8; i++)
{
vec4 pos = u_Lights[i * 2];
vec4 color = u_Lights[i * 2 + 1];
vec3 s, r;

if (pos.w > 0.0)
{
/* Point light -- no attenuation yet */
s = normalize((in_View * pos).xyz - pass_Vertex.xyz);
r = reflect(-s, pass_TNormal);
}
else
{
/* Directional light */
s = normalize(-pos.xyz);
r = reflect(s, pass_TNormal);
}

float sdotn = max(dot(s, pass_TNormal), 0.0);
diffuse += color.xyz * sdotn;
if (sdotn > 0.0)
specular += color.xyz * specular_reflect
* pow(max(dot(r, v), 0.0), specular_power);
}

vec3 light = ambient + diffuse + specular;

vec4 world_vertex = in_Inv_ModelView * pass_Vertex;
vec4 world_normal = in_Inv_ModelView * vec4(pass_TNormal, 1.0);

float dam_perc = in_Damage / (0.1 * 40);
float PI = 3.14159265358979323846264;
dam_perc = (sin(PI * (dam_perc - 0.5)) * 0.5 + 0.5);
dam_perc *= dam_perc;
dam_perc = 1.0 - dam_perc;
float mod = 2.0;
float transp = dam_perc;
/*
abs(sin(world_vertex.x * mod) * dam_perc * 0.5 + 0.5) *
abs(sin(world_vertex.y * mod) * dam_perc * 0.5 + 0.5) *
abs(sin(world_vertex.z * mod) * dam_perc * 0.5 + 0.5)
*/

//vec4 real_color = mix(pass_Color, vec4(1.2, 1.2, 1.2, 1.0), in_Damage);
// - in_Damage
gl_FragColor = pass_Color * vec4(light, (in_Damage == 0)?(1.0):(transp));
}

[vert.hlsl]

void main(float3 in_Vertex : POSITION,
float3 in_Normal : NORMAL,
float4 in_Color : COLOR,
uniform float4x4 in_ModelView,
uniform float4x4 in_Model,
uniform float4x4 in_Proj,
uniform float3x3 in_NormalMat,
out float4 pass_Vertex : TEXCOORD0,
out float3 pass_TNormal : TEXCOORD1,
out float4 pass_Color : COLOR,
out float4 out_Position : POSITION)
{
float4 eye = mul(in_ModelView, float4(in_Vertex, 1.0));
float3 tnorm = normalize(mul(in_NormalMat, in_Normal));

pass_Vertex = eye;
pass_TNormal = tnorm;
#ifdef _XBOX
pass_Color = in_Color.abgr;
#else
pass_Color = in_Color;
#endif

out_Position = mul(in_Proj, eye);
}

[frag.hlsl]

void main(float4 pass_Vertex : TEXCOORD0,
float3 pass_TNormal : TEXCOORD1,
float4 pass_Color : COLOR,
uniform float in_Damage,
out float4 out_FragColor : COLOR)
{
float3 in_LightDir = float3(0.3, 0.3, 0.7);

/* Material properties */
float3 specular_reflect = float3(0.8, 0.75, 0.4);
float specular_power = 60.0;

/* World properties */
float ambient_mul = 0.5;
float3 ambient_color = float3(0.25, 0.2, 0.35);
float3 diffuse_color = float3(1.0, 1.0, 0.6);
float3 specular_color = float3(1.0, 1.0, 0.6);

float3 s = normalize(in_LightDir); /* normalize(pass_Vertex - lightpos); */
float3 v = normalize(-pass_Vertex.xyz);
float3 r = reflect(-s, pass_TNormal);

float3 ambient = ambient_color;
float sdotn = max(dot(s, pass_TNormal), 0.0);
float3 diffuse = diffuse_color * sdotn;
float3 specular = float3(0.0, 0.0, 0.0);
if (sdotn > 0.0)
specular = specular_color * specular_reflect
* pow(max(dot(r, v), 0.0), specular_power);
float3 light = ambient + diffuse + specular;

float4 real_color = in_Damage * float4(1.2, 1.2, 1.2, 1.0)
+ (1.0 - in_Damage) * pass_Color;
out_FragColor = real_color * float4(light, 1.0);
}


Loading…
Cancel
Save