commit x64 compilation from lulu cause the other branch dont seems to compile properly at home
This commit is contained in:
256
include/engine/core/geometry_bih.cpp
Normal file
256
include/engine/core/geometry_bih.cpp
Normal file
@ -0,0 +1,256 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "core/geometry_bih.h"
|
||||
#include "core/graphic_resource_factory.h"
|
||||
#include "metafile/nml_object.h"
|
||||
#include "log/log.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Core;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool GeometryBIH::FastPolyTest(uint ip, Vector4 &s, Vector4 &d, float t_max)
|
||||
{
|
||||
Polygon &pol = geometry->pol[ip];
|
||||
Vector4 &pn = geometry->pol_normal[ip];
|
||||
|
||||
float dnv = d.Dot(pn);
|
||||
if (dnv >= 0.f)
|
||||
return false; // backface
|
||||
|
||||
float t = (geometry->vtx[pol.binding[0]].Dot(pn) - s.Dot(pn)) / dnv;
|
||||
if ((t < 0) || ((t_max > 0) && (t > t_max)))
|
||||
return false; // Behind origin or beyond ray length.
|
||||
|
||||
// Make sure point is in polygon.
|
||||
GeometryBIHAccel &ca = acc[ip];
|
||||
|
||||
// Note that the intersection point if offset toward the polygon origin.
|
||||
float pu = s[ca.cu] + d[ca.cu] * t - geometry->vtx[pol.binding[0]][ca.cu];
|
||||
float pv = s[ca.cv] + d[ca.cv] * t - geometry->vtx[pol.binding[0]][ca.cv];
|
||||
|
||||
const float ray_epsilon = -0.000001f;
|
||||
|
||||
float *k = ca.k;
|
||||
for (int m = 1; m < (pol.vtx_count - 1); ++m)
|
||||
{
|
||||
float u = pv * k[0] + pu * k[1], v, w;
|
||||
if (u < ray_epsilon)
|
||||
goto next;
|
||||
v = pu * k[2] + pv * k[3];
|
||||
if (v < ray_epsilon)
|
||||
goto next;
|
||||
w = 1 - u - v;
|
||||
if (w < ray_epsilon)
|
||||
goto next;
|
||||
|
||||
return true;
|
||||
next:;
|
||||
k += 4;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void GeometryBIH::TraceLeaf(BIH::Node *leaf, float tmin, float tmax, BIH::Trace &, void *parm)
|
||||
{
|
||||
GeometryTrace *trace = (GeometryTrace *)parm;
|
||||
|
||||
uint *leaf_indice = (uint *)leaf->p;
|
||||
Vector4 *vtx = geometry->vtx;
|
||||
|
||||
// Test each polygon in leaf.
|
||||
for (uint n = 0; n < leaf->count; ++n)
|
||||
{
|
||||
uint idx = leaf_indice[n];
|
||||
Vector4 &pn = geometry->pol_normal[idx];
|
||||
Polygon &pol = geometry->pol[idx];
|
||||
Material *material = material_table[pol.material].material;
|
||||
|
||||
trace->tri_test += pol.vtx_count - 2;
|
||||
|
||||
// Reject back facing polygons.
|
||||
bool backface = false;
|
||||
float dnv = trace->d.Dot(pn);
|
||||
|
||||
if (dnv >= 0.f)
|
||||
{
|
||||
if (material->renderword & Material::Render_DoubleSided)
|
||||
backface = true;
|
||||
else
|
||||
continue;
|
||||
}
|
||||
float t = (vtx[pol.binding[0]].Dot(pn) - trace->s.Dot(pn)) / dnv;
|
||||
|
||||
// Reject intersections further away than the current best one.
|
||||
if (trace->has_i && (t >= trace->i_t))
|
||||
continue;
|
||||
// Plane is outside ray boundaries.
|
||||
if ((t < tmin) || (t > tmax))
|
||||
continue;
|
||||
|
||||
// Make sure point is in polygon.
|
||||
GeometryBIHAccel &ca = acc[idx];
|
||||
|
||||
// Note that the intersection point if offset toward the polygon origin.
|
||||
float pu = trace->s[ca.cu] + trace->d[ca.cu] * t - vtx[pol.binding[0]][ca.cu],
|
||||
pv = trace->s[ca.cv] + trace->d[ca.cv] * t - vtx[pol.binding[0]][ca.cv];
|
||||
|
||||
#define RAY_EPSILON -0.000001f
|
||||
|
||||
float *k = ca.k;
|
||||
for (int m = 1; m < (pol.vtx_count - 1); ++m)
|
||||
{
|
||||
float u = pv * k[0] + pu * k[1], v, w;
|
||||
if (u < RAY_EPSILON)
|
||||
goto next;
|
||||
v = pu * k[2] + pv * k[3];
|
||||
if (v < RAY_EPSILON)
|
||||
goto next;
|
||||
w = 1 - u - v;
|
||||
if (w < RAY_EPSILON)
|
||||
goto next;
|
||||
|
||||
trace->has_i = true;
|
||||
trace->i_t = t;
|
||||
|
||||
trace->ip = idx;
|
||||
trace->it = m - 1;
|
||||
trace->bi = pol_index[idx];
|
||||
trace->u = u;
|
||||
trace->v = v;
|
||||
trace->w = w;
|
||||
trace->g = geometry;
|
||||
trace->m = material;
|
||||
trace->st = material_table[pol.material].shader_tree;
|
||||
trace->backface = backface;
|
||||
|
||||
break; // No need to look further.
|
||||
next:;
|
||||
k += 4;
|
||||
}
|
||||
}
|
||||
}
|
||||
void GeometryBIH::RaytraceGeometry(GeometryTrace &trace, const Vector4 &s, const Vector4 &d, float l)
|
||||
{
|
||||
trace.ip = -1;
|
||||
trace.tri_test = 0;
|
||||
trace.has_i = false;
|
||||
trace.i_t = -1;
|
||||
trace.s = s;
|
||||
trace.d = d;
|
||||
|
||||
BIH::Trace bih_trace;
|
||||
Raytrace(bih_trace, s, d, l, (void *)&trace);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
bool GeometryBIH::BuildFromGeometry(ResourceFactory &gf, Geometry *g)
|
||||
{
|
||||
Free();
|
||||
|
||||
// Build geometry LUTs.
|
||||
geometry = g;
|
||||
geometry->ComputePolygonIndex(pol_index);
|
||||
|
||||
// Load geometry resources.
|
||||
material_table.Allocate(geometry->material_table.GetCount());
|
||||
for (uint n = 0; n < material_table.GetCount(); ++n)
|
||||
{
|
||||
sMaterial m(gf.LoadMaterial(geometry->material_table[n].name));
|
||||
|
||||
if (m.IsNull())
|
||||
return false;
|
||||
|
||||
if (!m->shader.IsEmpty())
|
||||
{
|
||||
sShaderTree tree(new ShaderTree);
|
||||
if (NML::LoadFromFile(*tree, m->shader))
|
||||
material_table[n].shader_tree = tree;
|
||||
}
|
||||
material_table[n].material = m;
|
||||
}
|
||||
|
||||
// Build volume array to build tree.
|
||||
Array <MinMax> varray(geometry->pol.GetCount());
|
||||
if (!varray)
|
||||
__ERR__(__LOG_E__ << "Failed to allocate volume objects.\n", false);
|
||||
|
||||
if (!acc.Allocate(geometry->pol.GetCount()))
|
||||
__ERR__(__LOG_E__ << "Failed to allocate point in polygon acceleration array.\n", false);
|
||||
|
||||
geometry->ComputePolygonNormal();
|
||||
|
||||
for (uint n = 0; n < geometry->pol.GetCount(); ++n)
|
||||
{
|
||||
Polygon &pol = geometry->pol[n];
|
||||
if (pol.vtx_count < 3)
|
||||
continue;
|
||||
|
||||
Vector4 *vtx = geometry->vtx;
|
||||
Vector4 u_edge = vtx[pol.binding[1]] - vtx[pol.binding[0]],
|
||||
v_edge = vtx[pol.binding[2]] - vtx[pol.binding[0]];
|
||||
geometry->pol_normal[n] = u_edge.Cross(v_edge).Normalized();
|
||||
|
||||
// Compute plane determinant.
|
||||
acc[n].d = -vtx[pol.binding[0]].Dot(geometry->pol_normal[n]);
|
||||
|
||||
// Determine most significant axis.
|
||||
Vector4 m = (vtx[pol.binding[1]] - vtx[pol.binding[0]]).Cross(vtx[pol.binding[2]] - vtx[pol.binding[0]]);
|
||||
float x = Types::Abs(m.x), y = Types::Abs(m.y), z = Types::Abs(m.z);
|
||||
|
||||
uint axis = 2;
|
||||
if ((x >= y) && (x >= z))
|
||||
axis = 0;
|
||||
else if ((y >= x) && (y >= z))
|
||||
axis = 1;
|
||||
|
||||
char cu = (axis + 1) % 3,
|
||||
cv = (axis + 2) % 3;
|
||||
acc[n].cu = cu; acc[n].cv = cv;
|
||||
|
||||
// Compute point in triangle fixed coefficients.
|
||||
if (acc[n].k.Allocate((pol.vtx_count - 2) * 4))
|
||||
{
|
||||
float *pk = acc[n].k.c_ptr();
|
||||
|
||||
for (int i = 1; i < (pol.vtx_count - 1); ++i)
|
||||
{
|
||||
Vector4 b = vtx[pol.binding[i + 1]] - vtx[pol.binding[0]],
|
||||
c = vtx[pol.binding[i]] - vtx[pol.binding[0]];
|
||||
|
||||
float k = 1.f / (b[cu] * c[cv] - b[cv] * c[cu]);
|
||||
*pk++ = b[cu] * k;
|
||||
*pk++ = -b[cv] * k;
|
||||
*pk++ = c[cv] * k;
|
||||
*pk++ = -c[cu] * k;
|
||||
}
|
||||
|
||||
// Build volume array.
|
||||
varray[n].mn = varray[n].mx = geometry->vtx[pol.binding[0]];
|
||||
for (uint m = 1; m < pol.vtx_count; ++m)
|
||||
{
|
||||
varray[n].mn.x = Types::Min(vtx[pol.binding[m]].x, varray[n].mn.x);
|
||||
varray[n].mn.y = Types::Min(vtx[pol.binding[m]].y, varray[n].mn.y);
|
||||
varray[n].mn.z = Types::Min(vtx[pol.binding[m]].z, varray[n].mn.z);
|
||||
varray[n].mx.x = Types::Max(vtx[pol.binding[m]].x, varray[n].mx.x);
|
||||
varray[n].mx.y = Types::Max(vtx[pol.binding[m]].y, varray[n].mx.y);
|
||||
varray[n].mx.z = Types::Max(vtx[pol.binding[m]].z, varray[n].mx.z);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Build(geometry->pol.GetCount(), &varray[0]);
|
||||
}
|
||||
void GeometryBIH::Free()
|
||||
{
|
||||
geometry = NULL;
|
||||
material_table.Free();
|
||||
|
||||
acc.Free();
|
||||
Tree::Free();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user