commit x64 compilation from lulu cause the other branch dont seems to compile properly at home
This commit is contained in:
238
include/engine/core/geometry_template.cpp
Normal file
238
include/engine/core/geometry_template.cpp
Normal file
@ -0,0 +1,238 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "core/geometry_template.h"
|
||||
#include "sort/sort.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Core;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void GeometryTemplate::ClearMaterials()
|
||||
{ materials.Clear(); }
|
||||
void GeometryTemplate::PushMaterial(const char *uri)
|
||||
{ materials.Add(uri); }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
#define __AssertPolygon if (!polygon) __ERRRAW__(__LOG_E__ << "You must begin a polygon before pushing attributes.\n")
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void GeometryTemplate::BeginPolygon()
|
||||
{ polygon = new Polygon; }
|
||||
void GeometryTemplate::PushVertex(const Vector4 &v)
|
||||
{ __AssertPolygon
|
||||
polygon->vertex.Add(v); }
|
||||
void GeometryTemplate::PushNormal(const Vector4 &n)
|
||||
{ __AssertPolygon
|
||||
polygon->normal.Add(n); }
|
||||
void GeometryTemplate::PushColor(const Color &c)
|
||||
{ __AssertPolygon
|
||||
polygon->color.Add(c); }
|
||||
void GeometryTemplate::PushUV(uint channel, const Vector2 &uv)
|
||||
{ __AssertPolygon
|
||||
polygon->uv[channel].Add(uv); }
|
||||
void GeometryTemplate::EndPolygon(ushort material)
|
||||
{
|
||||
if (polygon)
|
||||
{
|
||||
polygon->material = material;
|
||||
polygons.Add(polygon.Detach());
|
||||
}
|
||||
else
|
||||
__LOG_E__ << "You must begin a polygon before ending it.\n";
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Vector4 GeometryTemplate::GetVertex(const PolygonVertex &pv)
|
||||
{ return polygons[pv.ipoly]->vertex[pv.ivertex]; }
|
||||
Vector4 GeometryTemplate::GetNormal(const PolygonVertex &pv)
|
||||
{ return polygons[pv.ipoly]->normal[pv.ivertex]; }
|
||||
Vector2 GeometryTemplate::GetUV(uint channel, const PolygonVertex &pv)
|
||||
{ return polygons[pv.ipoly]->uv[channel][pv.ivertex]; }
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Geometry *GeometryTemplate::Instantiate(const char *name)
|
||||
{
|
||||
if (!materials.GetCount())
|
||||
__ERR__(__LOG_E__ << "Cannot instantiate a geometry with no material array.\n", NULL)
|
||||
|
||||
AutoPtr <Geometry> geo(new Geometry);
|
||||
if (geo.IsNull())
|
||||
__ERR__(__LOG_E__ << "Geometry allocation error.\n", NULL)
|
||||
geo->name = name;
|
||||
|
||||
// Build vertex merge table.
|
||||
uint vtx_per_poly_count = 0;
|
||||
ListForeachPtr(Polygon *, p, polygons)
|
||||
vtx_per_poly_count += p->vertex.GetCount();
|
||||
|
||||
typedef GS::Sort<float, uint> SortVPP;
|
||||
|
||||
Array <PolygonVertex> raw_v(vtx_per_poly_count);
|
||||
Array <SortVPP::Entry> qs_e(vtx_per_poly_count);
|
||||
|
||||
vtx_per_poly_count = 0;
|
||||
uint ipoly = 0;
|
||||
Vector4 &support = polygons[0]->vertex[0];
|
||||
|
||||
ListForeachPtr(Polygon *, p, polygons)
|
||||
{
|
||||
for (uint ivertex = 0; ivertex < p->vertex.GetCount(); ++ivertex)
|
||||
{
|
||||
// Track this vertex.
|
||||
raw_v[vtx_per_poly_count].ipoly = ipoly;
|
||||
raw_v[vtx_per_poly_count].ivertex = ivertex;
|
||||
|
||||
// Quick-sort entry.
|
||||
qs_e[vtx_per_poly_count].o = vtx_per_poly_count;
|
||||
qs_e[vtx_per_poly_count].v = Vector4::Dist2(GetVertex(raw_v[vtx_per_poly_count]), support);
|
||||
|
||||
++vtx_per_poly_count;
|
||||
}
|
||||
++ipoly;
|
||||
}
|
||||
|
||||
// Compute polygon start offsets.
|
||||
Array <int> poly_offset(polygons.GetCount());
|
||||
|
||||
int poly_binding_start_offset = 0;
|
||||
for (uint n = 0; n < polygons.GetCount(); ++n)
|
||||
{
|
||||
poly_offset[n] = poly_binding_start_offset;
|
||||
poly_binding_start_offset += polygons[n]->vertex.GetCount();
|
||||
}
|
||||
|
||||
// Count merged vertex.
|
||||
SortVPP::QuickSort(vtx_per_poly_count, qs_e);
|
||||
geo->binding.Allocate(vtx_per_poly_count);
|
||||
|
||||
uint packed_vtx_count = 0;
|
||||
for (uint n = 0; n < vtx_per_poly_count; )
|
||||
{
|
||||
PolygonVertex &pv = raw_v[qs_e[n].o];
|
||||
geo->binding[poly_offset[pv.ipoly] + pv.ivertex] = packed_vtx_count;
|
||||
|
||||
uint m = n + 1;
|
||||
for (; m < vtx_per_poly_count; ++m)
|
||||
{
|
||||
if (Vector4::Dist2(GetVertex(raw_v[qs_e[n].o]), GetVertex(raw_v[qs_e[m].o])) > merge_threshold)
|
||||
break;
|
||||
|
||||
PolygonVertex &pv = raw_v[qs_e[m].o];
|
||||
geo->binding[poly_offset[pv.ipoly] + pv.ivertex] = packed_vtx_count;
|
||||
}
|
||||
|
||||
++packed_vtx_count;
|
||||
n = m;
|
||||
}
|
||||
|
||||
// Pack vertices.
|
||||
geo->vtx.Allocate(packed_vtx_count);
|
||||
|
||||
packed_vtx_count = 0;
|
||||
for (uint n = 0; n < vtx_per_poly_count; )
|
||||
{
|
||||
uint m = n + 1;
|
||||
for (; m < vtx_per_poly_count; ++m)
|
||||
if (Vector4::Dist2(GetVertex(raw_v[qs_e[n].o]), GetVertex(raw_v[qs_e[m].o])) > merge_threshold)
|
||||
break;
|
||||
|
||||
geo->vtx[packed_vtx_count++] = GetVertex(raw_v[qs_e[n].o]);
|
||||
n = m;
|
||||
}
|
||||
|
||||
// Build polygons.
|
||||
geo->pol.Allocate(polygons.GetCount());
|
||||
|
||||
uint pol_count = 0, pol_bind = 0;
|
||||
ListForeachPtr(Polygon *, p, polygons)
|
||||
{
|
||||
if (p->vertex.GetCount() > 65535)
|
||||
__LOG_W__ << "Too many vertices in polygon " << pol_count << ".\n";
|
||||
|
||||
geo->pol[pol_count].vtx_count = (ushort)p->vertex.GetCount();
|
||||
geo->pol[pol_count].binding = &geo->binding[pol_bind];
|
||||
pol_bind += p->vertex.GetCount();
|
||||
|
||||
if (p->material > materials.GetCount())
|
||||
{
|
||||
p->material = 0;
|
||||
__LOG_W__ << "Polygon " << pol_count << " is referencing a material outside of the material table.\n";
|
||||
}
|
||||
geo->pol[pol_count].material = p->material;
|
||||
++pol_count;
|
||||
}
|
||||
|
||||
// Output remaining attributes.
|
||||
Polygon *poly = polygons[0];
|
||||
|
||||
bool has_normal = asbool(poly->normal.GetCount());
|
||||
bool has_color = asbool(poly->color.GetCount());
|
||||
|
||||
bool has_uv[__UV_PER_GEOMETRY__];
|
||||
for (uint n = 0; n < __UV_PER_GEOMETRY__; ++n)
|
||||
has_uv[n] = asbool(poly->uv[n].GetCount());
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
#define __CreateAttribute(__Destination, __Attrib)\
|
||||
{\
|
||||
if (__Destination.Allocate(vtx_per_poly_count))\
|
||||
{\
|
||||
uint cpol = 0, cvpl = 0;\
|
||||
ListForeachPtr(Polygon *, p, polygons)\
|
||||
{\
|
||||
if (p->vertex.GetCount() != __Attrib.GetCount())\
|
||||
__LOG_W__ << "Incoherent normal count in polygon " << cpol << ".\n";\
|
||||
else\
|
||||
for (uint n = 0; n < p->vertex.GetCount(); ++n)\
|
||||
__Destination[cvpl + n] = __Attrib[n];\
|
||||
\
|
||||
cvpl += p->vertex.GetCount();\
|
||||
++cpol;\
|
||||
}\
|
||||
}\
|
||||
else\
|
||||
__LOG_E__ << "Failed to allocate attribute array while creating geometry '" << name << "'.\n";\
|
||||
}
|
||||
//--------------------------------------------------------------------------
|
||||
|
||||
if (has_normal)
|
||||
__CreateAttribute(geo->vtx_normal, p->normal)
|
||||
if (has_color)
|
||||
__CreateAttribute(geo->rgb, p->color)
|
||||
|
||||
for (uint i_uv = 0; i_uv < __UV_PER_GEOMETRY__; ++i_uv)
|
||||
if (has_uv[i_uv])
|
||||
__CreateAttribute(geo->uv[i_uv], p->uv[i_uv])
|
||||
|
||||
if (!geo->material_table.Allocate(materials.GetCount()))
|
||||
__ERR__(__LOG_E__ << "Failed to allocate material array when creating geometry '" << name << "'.\n", NULL)
|
||||
|
||||
uint slot_count = 0;
|
||||
ListForeach(String, n, materials)
|
||||
geo->material_table[slot_count++].name = n.Object();
|
||||
|
||||
return geo.Detach();
|
||||
}
|
||||
void GeometryTemplate::Clear()
|
||||
{
|
||||
polygon = NULL;
|
||||
polygons.Clear();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
GeometryTemplate::GeometryTemplate()
|
||||
{
|
||||
merge_threshold = 0.0001f;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user