commit x64 compilation from lulu cause the other branch dont seems to compile properly at home
This commit is contained in:
275
include/modules/raytracer/raytracer_scene.cpp
Normal file
275
include/modules/raytracer/raytracer_scene.cpp
Normal file
@ -0,0 +1,275 @@
|
||||
/* -----------------------------------------------------------------------------
|
||||
GSFramework
|
||||
Copyright 2001-2013 Emmanuel Julien. All Rights Reserved.
|
||||
----------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
#include "raytracer/raytracer_scene.h"
|
||||
#include "scene3d/mobject.h"
|
||||
#include "scene3d/mlight.h"
|
||||
#include "scene3d/scene.h"
|
||||
#include "scene3d/instance.h"
|
||||
#include "scene3d/group.h"
|
||||
#include "core/geometry_bih.h"
|
||||
#include "metafile/nml_object.h"
|
||||
|
||||
using namespace GS;
|
||||
using namespace GS::Core;
|
||||
using namespace GS::Raytrace;
|
||||
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void SceneBIH::ResetStats()
|
||||
{
|
||||
ray_count = 0;
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
void SceneBIH::TraceLeaf(BIH::Node *leaf, float tmin, float tmax, BIH::Trace &trace, void *parm)
|
||||
{
|
||||
Vector4 &s = trace.s, &d = trace.d;
|
||||
Trace *s_trace = (Trace *)parm;
|
||||
uint *leaf_indice = (uint *)leaf->p;
|
||||
|
||||
for (uint n = 0; n < leaf->count; ++n)
|
||||
{
|
||||
Core::Object *o = obj[leaf_indice[n]].o;
|
||||
IGeometryTree *tree = obj[leaf_indice[n]].tree;
|
||||
|
||||
// Raytrace object in local space.
|
||||
Vector4 local_s = s * o->GetInverseMatrix(), local_d;
|
||||
o->GetInverseMatrix().ApplyRotation(&local_d, &d);
|
||||
|
||||
GeometryTrace geo_trace;
|
||||
tree->RaytraceGeometry(geo_trace, local_s, local_d, tmax);
|
||||
|
||||
if (!geo_trace.has_i)
|
||||
continue;
|
||||
|
||||
// Integrate result.
|
||||
if (!s_trace->has_i || (geo_trace.i_t < s_trace->i_t))
|
||||
{
|
||||
/*
|
||||
Note: Do not copy the complete geo_trace, we do not want
|
||||
to duplicate trace stacks.
|
||||
*/
|
||||
*((GeometryTraceBase *)s_trace) = ((GeometryTraceBase &)geo_trace);
|
||||
|
||||
s_trace->has_i = true;
|
||||
|
||||
s_trace->o = o;
|
||||
s_trace->tri_test += geo_trace.tri_test;
|
||||
}
|
||||
}
|
||||
}
|
||||
void SceneBIH::RaytraceScene(Trace &trace, const Vector4 &s, const Vector4 &d, float l)
|
||||
{
|
||||
ray_count++;
|
||||
|
||||
trace.s = s;
|
||||
trace.d = d;
|
||||
|
||||
BIH::Trace bih_trace;
|
||||
Tree::Raytrace(bih_trace, s, d, l, (void *)&trace);
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
//------------------------------------------------------------------------------
|
||||
Geometry *SceneBIH::TranslateGeometry(Geometry *g) const
|
||||
{
|
||||
if (obj && g)
|
||||
for (uint n = 0; n < obj.GetCount(); ++n)
|
||||
if (obj[n].g == g)
|
||||
return obj[n].og;
|
||||
return g;
|
||||
}
|
||||
void SceneBIH::AddObject(ResourceFactory &gf, S3D::MObject *o, uint &obj_count, MinMax *varray, bool shadow)
|
||||
{
|
||||
if (!o->isActive())
|
||||
return;
|
||||
if (o->geometry.IsEmpty() || !o->GetBaseItem()->opacity)
|
||||
return;
|
||||
if (o->mitem_flags.IsSet(S3D::MItem::Flag_IsHelper | S3D::MItem::Flag_EditorHidden | S3D::MItem::Flag_EditorLocked))
|
||||
return;
|
||||
|
||||
// Grab object geometry.
|
||||
Geometry *g = gf.LoadGeometry(o->geometry);
|
||||
if (!g)
|
||||
return;
|
||||
|
||||
obj[obj_count].og = g; // Store original geometry to map back from skinned geometry.
|
||||
if (!g->material_table.GetCount() || !g->pol.GetCount())
|
||||
return;
|
||||
|
||||
if (shadow)
|
||||
{
|
||||
if (g->flag.IsSet(Geometry::FlagNullShadowProxy))
|
||||
return;
|
||||
if (!g->shadow_proxy.IsEmpty())
|
||||
g = gf.LoadGeometry(g->shadow_proxy);
|
||||
}
|
||||
|
||||
// Perform skinning.
|
||||
if (o->HasSkin() && g->skin)
|
||||
{
|
||||
Skin *skin = o->GetSkin();
|
||||
|
||||
// Serialize geometry.
|
||||
using namespace NML;
|
||||
|
||||
File file;
|
||||
file.AddRoot(g->AsMetaTag());
|
||||
|
||||
Geometry *sg = new Geometry;
|
||||
LoadFromFile(*sg, file);
|
||||
|
||||
// Build required structures upfront.
|
||||
sg->ComputeVertexNormal();
|
||||
sg->ComputeVertexTangent();
|
||||
|
||||
// Vertex skinning.
|
||||
for (uint n = 0; n < sg->vtx.GetCount(); ++n)
|
||||
{
|
||||
Vector4 v(0, 0, 0);
|
||||
for (int b = 0; b < 4; ++b)
|
||||
{
|
||||
if (!sg->skin[n].w[b])
|
||||
break;
|
||||
v += (sg->vtx[n] * skin->bones_mtx[sg->skin[n].bone_index[b]]) * sg->skin[n].w[b];
|
||||
}
|
||||
sg->vtx[n] = v;
|
||||
}
|
||||
|
||||
// Normal skinning.
|
||||
Vector4 s, w;
|
||||
int tt = 0;
|
||||
for (uint p = 0; p < sg->pol.GetCount(); ++p)
|
||||
for (uint n = 0; n < sg->pol[p].vtx_count; ++n)
|
||||
{
|
||||
s.Set(0, 0, 0);
|
||||
for (int b = 0; b < 4; ++b)
|
||||
{
|
||||
int i = sg->pol[p].binding[n];
|
||||
if (!sg->skin[i].w[b])
|
||||
break;
|
||||
skin->bones_mtx[sg->skin[i].bone_index[b]].ApplyRotation(&w, &sg->vtx_normal[tt]);
|
||||
s += w * sg->skin[i].w[b];
|
||||
}
|
||||
sg->vtx_normal[tt++] = s;
|
||||
}
|
||||
|
||||
// Tangent base skinning.
|
||||
Vector4 _b, _t;
|
||||
tt = 0;
|
||||
for (uint p = 0; p < sg->pol.GetCount(); ++p)
|
||||
for (uint n = 0; n < sg->pol[p].vtx_count; ++n)
|
||||
{
|
||||
_b.Set(0, 0, 0);
|
||||
_t.Set(0, 0, 0);
|
||||
for (int b = 0; b < 4; ++b)
|
||||
{
|
||||
int i = sg->pol[p].binding[n];
|
||||
if (!sg->skin[i].w[b])
|
||||
break;
|
||||
|
||||
skin->bones_mtx[sg->skin[i].bone_index[b]].ApplyRotation(&w, &sg->vtx_tangent[tt].B);
|
||||
_b += w * sg->skin[i].w[b];
|
||||
skin->bones_mtx[sg->skin[i].bone_index[b]].ApplyRotation(&w, &sg->vtx_tangent[tt].T);
|
||||
_t += w * sg->skin[i].w[b];
|
||||
}
|
||||
sg->vtx_tangent[tt].B = _b;
|
||||
sg->vtx_tangent[tt].T = _t;
|
||||
tt++;
|
||||
}
|
||||
|
||||
// Use as the base geometry.
|
||||
// but first copy the material from the base material
|
||||
sg->material_table.Allocate(g->material_table.GetCount());
|
||||
for (uint k = 0; k < g->material_table.GetCount(); ++k)
|
||||
sg->material_table[k] = g->material_table[k];
|
||||
|
||||
g = sg;
|
||||
}
|
||||
|
||||
// Prepare geometry.
|
||||
IGeometryTree *tree = new GeometryBIHTree;
|
||||
tree->BuildFromGeometry(gf, g);
|
||||
|
||||
// Build minmax for the transformed geometry.
|
||||
varray[obj_count] = g->ComputeMinMax(&o->GetMatrix());
|
||||
|
||||
obj[obj_count].g = g;
|
||||
obj[obj_count].tree = tree;
|
||||
obj[obj_count++].o = o;
|
||||
}
|
||||
bool SceneBIH::SetScene(ResourceFactory &gf, const S3D::Scene *s, bool shadow)
|
||||
{
|
||||
Free();
|
||||
|
||||
using namespace S3D;
|
||||
|
||||
SharedList <MObject *> objects;
|
||||
s->GetItemListByType(objects);
|
||||
SharedList <Instance *> instances;
|
||||
s->GetItemListByType(instances);
|
||||
|
||||
// Grab the scene content.
|
||||
uint obj_count = 0;
|
||||
ListForeachPtr(MObject *, o, objects)
|
||||
if (!o->geometry.IsEmpty())
|
||||
obj_count++;
|
||||
|
||||
// Count the instance objects.
|
||||
ListForeachPtr(Instance *, i, instances)
|
||||
{
|
||||
if (!i->instance_scene)
|
||||
{
|
||||
if (!(i->instance_scene = new Scene(s->GetVM())))
|
||||
continue;
|
||||
|
||||
i->instance_scene->FromMetaFileStoreGroup(i->template_path, &i->instance_group, SceneIOObject | SceneIOLight);
|
||||
if (i->instance_group != NULL)
|
||||
i->instance_group->SetRootItem(i);
|
||||
}
|
||||
|
||||
if (i->instance_group)
|
||||
ListForeachPtr(MItem *, ig, i->instance_group->GetItemList())
|
||||
if (ig->GetItemType() == Type_Object && !((MObject *)ig)->geometry.IsEmpty())
|
||||
obj_count++;
|
||||
}
|
||||
|
||||
if (!obj_count)
|
||||
return true;
|
||||
|
||||
if (!obj.Allocate(obj_count))
|
||||
__ERR__(__LOG_E__ << "Failed to grab scene to raytracer.\n", false)
|
||||
|
||||
// Build scene tree and object trees.
|
||||
Array <MinMax> varray(obj_count);
|
||||
if (!varray)
|
||||
__ERR__(__LOG_E__ << "Failed to allocate volume array to build scene tree.\n", false)
|
||||
|
||||
obj_count = 0;
|
||||
|
||||
ListForeachPtr(MObject *, o, objects)
|
||||
AddObject(gf, o, obj_count, varray, shadow);
|
||||
|
||||
// Add the instance objects.
|
||||
ListForeachPtr(Instance *, i, instances)
|
||||
if (i->instance_group)
|
||||
ListForeachPtr(MItem *, ig, i->instance_group->GetItemList())
|
||||
if (ig->GetItemType() == Type_Object && !((MObject *)ig)->geometry.IsEmpty())
|
||||
AddObject(gf, ((MObject *)ig), obj_count, varray, shadow);
|
||||
|
||||
// Build tree.
|
||||
if (!Build(obj_count, varray))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
void SceneBIH::Free()
|
||||
{
|
||||
obj.Free();
|
||||
Tree::Free();
|
||||
}
|
||||
//------------------------------------------------------------------------------
|
||||
Reference in New Issue
Block a user