mirror of
https://github.com/ZDoom/ZDRay.git
synced 2025-01-24 16:51:08 +00:00
- Switch the raytrace function to use different collision routines
This commit is contained in:
parent
99a4ffa69f
commit
8958790fed
9 changed files with 247 additions and 137 deletions
|
@ -3,6 +3,8 @@
|
||||||
|
|
||||||
#include "framework/tarray.h"
|
#include "framework/tarray.h"
|
||||||
#include "lightmap/kexlib/math/mathlib.h"
|
#include "lightmap/kexlib/math/mathlib.h"
|
||||||
|
#include "lightmap/collision.h"
|
||||||
|
#include <memory>
|
||||||
#undef MIN
|
#undef MIN
|
||||||
#undef MAX
|
#undef MAX
|
||||||
|
|
||||||
|
@ -345,6 +347,11 @@ struct FLevel
|
||||||
|
|
||||||
// Dlight helpers
|
// Dlight helpers
|
||||||
|
|
||||||
|
TArray<kexVec3> MeshVertices;
|
||||||
|
TArray<unsigned int> MeshElements;
|
||||||
|
TArray<int> MeshSurfaces;
|
||||||
|
std::unique_ptr<TriangleMeshShape> CollisionMesh;
|
||||||
|
|
||||||
leaf_t *leafs = nullptr;
|
leaf_t *leafs = nullptr;
|
||||||
uint8_t *mapPVS = nullptr;
|
uint8_t *mapPVS = nullptr;
|
||||||
|
|
||||||
|
|
|
@ -28,6 +28,24 @@ typedef unsigned int uint32;
|
||||||
typedef signed int int32;
|
typedef signed int int32;
|
||||||
#include "framework/xs_Float.h"
|
#include "framework/xs_Float.h"
|
||||||
|
|
||||||
|
static void CopyUDMFString(char *dest, int destlen, const char *udmfvalue)
|
||||||
|
{
|
||||||
|
destlen--;
|
||||||
|
|
||||||
|
char endchar = 0;
|
||||||
|
if (udmfvalue[0] == '"' || udmfvalue[0] == '\'')
|
||||||
|
{
|
||||||
|
endchar = udmfvalue[0];
|
||||||
|
udmfvalue++;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (int i = 0; i < destlen && udmfvalue[i] != 0 && udmfvalue[i] != endchar; i++)
|
||||||
|
{
|
||||||
|
*(dest++) = udmfvalue[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
*dest = 0;
|
||||||
|
}
|
||||||
|
|
||||||
class StringBuffer
|
class StringBuffer
|
||||||
{
|
{
|
||||||
|
@ -251,6 +269,14 @@ void FProcessor::ParseSidedef(IntSideDef *sd)
|
||||||
{
|
{
|
||||||
SC_MustGetStringName("{");
|
SC_MustGetStringName("{");
|
||||||
sd->sector = NO_INDEX;
|
sd->sector = NO_INDEX;
|
||||||
|
sd->textureoffset = 0;
|
||||||
|
sd->rowoffset = 0;
|
||||||
|
sd->toptexture[0] = '-';
|
||||||
|
sd->toptexture[1] = 0;
|
||||||
|
sd->midtexture[0] = '-';
|
||||||
|
sd->midtexture[1] = 0;
|
||||||
|
sd->bottomtexture[0] = '-';
|
||||||
|
sd->bottomtexture[1] = 0;
|
||||||
while (!SC_CheckString("}"))
|
while (!SC_CheckString("}"))
|
||||||
{
|
{
|
||||||
const char *value;
|
const char *value;
|
||||||
|
@ -262,6 +288,27 @@ void FProcessor::ParseSidedef(IntSideDef *sd)
|
||||||
continue; // do not store in props
|
continue; // do not store in props
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (stricmp(key, "texturetop") == 0)
|
||||||
|
{
|
||||||
|
CopyUDMFString(sd->toptexture, 8, value);
|
||||||
|
}
|
||||||
|
else if (stricmp(key, "texturemiddle") == 0)
|
||||||
|
{
|
||||||
|
CopyUDMFString(sd->midtexture, 8, value);
|
||||||
|
}
|
||||||
|
else if (stricmp(key, "texturebottom") == 0)
|
||||||
|
{
|
||||||
|
CopyUDMFString(sd->bottomtexture, 8, value);
|
||||||
|
}
|
||||||
|
else if (stricmp(key, "offsetx_mid") == 0)
|
||||||
|
{
|
||||||
|
sd->textureoffset = CheckInt(key);
|
||||||
|
}
|
||||||
|
else if (stricmp(key, "offsety_mid") == 0)
|
||||||
|
{
|
||||||
|
sd->rowoffset = CheckInt(key);
|
||||||
|
}
|
||||||
|
|
||||||
// now store the key in its unprocessed form
|
// now store the key in its unprocessed form
|
||||||
UDMFKey k = {key, value};
|
UDMFKey k = {key, value};
|
||||||
sd->props.Push(k);
|
sd->props.Push(k);
|
||||||
|
@ -274,25 +321,6 @@ void FProcessor::ParseSidedef(IntSideDef *sd)
|
||||||
//
|
//
|
||||||
//===========================================================================
|
//===========================================================================
|
||||||
|
|
||||||
static void CopyUDMFString(char *dest, int destlen, const char *udmfvalue)
|
|
||||||
{
|
|
||||||
destlen--;
|
|
||||||
|
|
||||||
char endchar = 0;
|
|
||||||
if (udmfvalue[0] == '"' || udmfvalue[0] == '\'')
|
|
||||||
{
|
|
||||||
endchar = udmfvalue[0];
|
|
||||||
udmfvalue++;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i = 0; i < destlen && udmfvalue[i] != 0 && udmfvalue[i] != endchar; i++)
|
|
||||||
{
|
|
||||||
*(dest++) = udmfvalue[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
*dest = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FProcessor::ParseSector(IntSector *sec)
|
void FProcessor::ParseSector(IntSector *sec)
|
||||||
{
|
{
|
||||||
memset(&sec->data, 0, sizeof(sec->data));
|
memset(&sec->data, 0, sizeof(sec->data));
|
||||||
|
|
|
@ -26,8 +26,8 @@
|
||||||
#undef min
|
#undef min
|
||||||
#undef max
|
#undef max
|
||||||
|
|
||||||
TriangleMeshShape::TriangleMeshShape(const kexVec3 *vertices, int num_vertices, const unsigned int *elements, int num_elements)
|
TriangleMeshShape::TriangleMeshShape(const kexVec3 *vertices, int num_vertices, const unsigned int *elements, int num_elements, const int *surfaces)
|
||||||
: vertices(vertices), num_vertices(num_vertices), elements(elements), num_elements(num_elements), root(-1)
|
: vertices(vertices), num_vertices(num_vertices), elements(elements), num_elements(num_elements), surfaces(surfaces)
|
||||||
{
|
{
|
||||||
int num_triangles = num_elements / 3;
|
int num_triangles = num_elements / 3;
|
||||||
if (num_triangles <= 0)
|
if (num_triangles <= 0)
|
||||||
|
@ -71,6 +71,15 @@ bool TriangleMeshShape::find_any_hit(TriangleMeshShape *shape, const kexVec3 &ra
|
||||||
return find_any_hit(shape, ray_start, ray_end, shape->root);
|
return find_any_hit(shape, ray_start, ray_end, shape->root);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TraceHit TriangleMeshShape::find_first_hit(TriangleMeshShape *shape, const kexVec3 &ray_start, const kexVec3 &ray_end)
|
||||||
|
{
|
||||||
|
TraceHit hit;
|
||||||
|
find_first_hit(shape, ray_start, ray_end, shape->root, &hit);
|
||||||
|
if (hit.surface != -1)
|
||||||
|
hit.surface = shape->surfaces[hit.surface / 3];
|
||||||
|
return hit;
|
||||||
|
}
|
||||||
|
|
||||||
float TriangleMeshShape::sweep(TriangleMeshShape *shape1, SphereShape *shape2, int a, const kexVec3 &target)
|
float TriangleMeshShape::sweep(TriangleMeshShape *shape1, SphereShape *shape2, int a, const kexVec3 &target)
|
||||||
{
|
{
|
||||||
if (sweep_overlap_bv_sphere(shape1, shape2, a, target))
|
if (sweep_overlap_bv_sphere(shape1, shape2, a, target))
|
||||||
|
@ -178,6 +187,27 @@ bool TriangleMeshShape::find_any_hit(TriangleMeshShape *shape, const kexVec3 &ra
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void TriangleMeshShape::find_first_hit(TriangleMeshShape *shape, const kexVec3 &ray_start, const kexVec3 &ray_end, int a, TraceHit *hit)
|
||||||
|
{
|
||||||
|
if (overlap_bv_ray(shape, ray_start, ray_end, a))
|
||||||
|
{
|
||||||
|
if (shape->is_leaf(a))
|
||||||
|
{
|
||||||
|
float t = intersect_triangle_ray(shape, ray_start, ray_end, a);
|
||||||
|
if (t < hit->fraction)
|
||||||
|
{
|
||||||
|
hit->fraction = t;
|
||||||
|
hit->surface = shape->nodes[a].element_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
find_first_hit(shape, ray_start, ray_end, shape->nodes[a].left, hit);
|
||||||
|
find_first_hit(shape, ray_start, ray_end, shape->nodes[a].right, hit);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
bool TriangleMeshShape::overlap_bv_ray(TriangleMeshShape *shape, const kexVec3 &ray_start, const kexVec3 &ray_end, int a)
|
bool TriangleMeshShape::overlap_bv_ray(TriangleMeshShape *shape, const kexVec3 &ray_start, const kexVec3 &ray_end, int a)
|
||||||
{
|
{
|
||||||
return IntersectionTest::ray_aabb(ray_start, ray_end, shape->nodes[a].aabb) == IntersectionTest::overlap;
|
return IntersectionTest::ray_aabb(ray_start, ray_end, shape->nodes[a].aabb) == IntersectionTest::overlap;
|
||||||
|
@ -194,6 +224,49 @@ float TriangleMeshShape::intersect_triangle_ray(TriangleMeshShape *shape, const
|
||||||
shape->vertices[shape->elements[start_element + 2]]
|
shape->vertices[shape->elements[start_element + 2]]
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#if 1
|
||||||
|
|
||||||
|
kexVec3 e1 = p[1] - p[0];
|
||||||
|
kexVec3 e2 = p[2] - p[0];
|
||||||
|
|
||||||
|
kexVec3 triangleNormal = kexVec3::Cross(e1, e2);
|
||||||
|
float dist = kexVec3::Dot(p[0], triangleNormal);
|
||||||
|
float distA = kexVec3::Dot(ray_start, triangleNormal) - dist;
|
||||||
|
float distB = kexVec3::Dot(ray_end, triangleNormal) - dist;
|
||||||
|
|
||||||
|
if (distA * distB >= 0.0f)
|
||||||
|
return 1.0f;
|
||||||
|
|
||||||
|
// Backface check
|
||||||
|
//if (distA < 0.0f)
|
||||||
|
// return 1.0f;
|
||||||
|
|
||||||
|
float projLength = distA - distB;
|
||||||
|
float distance = (distA) / (projLength);
|
||||||
|
if (distance > 1.0f)
|
||||||
|
return 1.0f;
|
||||||
|
|
||||||
|
float edgeTolerance = triangleNormal.LengthSq() * -0.0001f;
|
||||||
|
kexVec3 point = ray_start * (1.0f - distance) + ray_end * distance;
|
||||||
|
|
||||||
|
kexVec3 v0p = p[0] - point;
|
||||||
|
kexVec3 v1p = p[1] - point;
|
||||||
|
kexVec3 cp0 = kexVec3::Cross(v0p, v1p);
|
||||||
|
if (kexVec3::Dot(cp0, triangleNormal) < edgeTolerance)
|
||||||
|
return 1.0f;
|
||||||
|
|
||||||
|
kexVec3 v2p = p[2] - point;
|
||||||
|
kexVec3 cp1 = kexVec3::Cross(v1p, v2p);
|
||||||
|
if (kexVec3::Dot(cp1, triangleNormal) < edgeTolerance)
|
||||||
|
return 1.0f;
|
||||||
|
|
||||||
|
kexVec3 cp2 = kexVec3::Cross(v2p, v0p);
|
||||||
|
if (kexVec3::Dot(cp2, triangleNormal) < edgeTolerance)
|
||||||
|
return 1.0f;
|
||||||
|
|
||||||
|
return distance;
|
||||||
|
|
||||||
|
#else
|
||||||
// Moeller–Trumbore ray-triangle intersection algorithm:
|
// Moeller–Trumbore ray-triangle intersection algorithm:
|
||||||
|
|
||||||
kexVec3 D = ray_end - ray_start;
|
kexVec3 D = ray_end - ray_start;
|
||||||
|
@ -206,6 +279,10 @@ float TriangleMeshShape::intersect_triangle_ray(TriangleMeshShape *shape, const
|
||||||
kexVec3 P = kexVec3::Cross(D, e2);
|
kexVec3 P = kexVec3::Cross(D, e2);
|
||||||
float det = kexVec3::Dot(e1, P);
|
float det = kexVec3::Dot(e1, P);
|
||||||
|
|
||||||
|
// Backface check
|
||||||
|
//if (det < 0.0f)
|
||||||
|
// return 1.0f;
|
||||||
|
|
||||||
// If determinant is near zero, ray lies in plane of triangle
|
// If determinant is near zero, ray lies in plane of triangle
|
||||||
if (det > -FLT_EPSILON && det < FLT_EPSILON)
|
if (det > -FLT_EPSILON && det < FLT_EPSILON)
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
|
@ -238,6 +315,7 @@ float TriangleMeshShape::intersect_triangle_ray(TriangleMeshShape *shape, const
|
||||||
|
|
||||||
// No hit, no win
|
// No hit, no win
|
||||||
return 1.0f;
|
return 1.0f;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TriangleMeshShape::sweep_overlap_bv_sphere(TriangleMeshShape *shape1, SphereShape *shape2, int a, const kexVec3 &target)
|
bool TriangleMeshShape::sweep_overlap_bv_sphere(TriangleMeshShape *shape1, SphereShape *shape2, int a, const kexVec3 &target)
|
||||||
|
|
|
@ -35,10 +35,16 @@ public:
|
||||||
float radius = 0.0f;
|
float radius = 0.0f;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct TraceHit
|
||||||
|
{
|
||||||
|
float fraction = 1.0f;
|
||||||
|
int surface = -1;
|
||||||
|
};
|
||||||
|
|
||||||
class TriangleMeshShape
|
class TriangleMeshShape
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
TriangleMeshShape(const kexVec3 *vertices, int num_vertices, const unsigned int *elements, int num_elements);
|
TriangleMeshShape(const kexVec3 *vertices, int num_vertices, const unsigned int *elements, int num_elements, const int *surfaces);
|
||||||
|
|
||||||
int get_min_depth();
|
int get_min_depth();
|
||||||
int get_max_depth();
|
int get_max_depth();
|
||||||
|
@ -51,25 +57,28 @@ public:
|
||||||
static bool find_any_hit(TriangleMeshShape *shape1, SphereShape *shape2);
|
static bool find_any_hit(TriangleMeshShape *shape1, SphereShape *shape2);
|
||||||
static bool find_any_hit(TriangleMeshShape *shape, const kexVec3 &ray_start, const kexVec3 &ray_end);
|
static bool find_any_hit(TriangleMeshShape *shape, const kexVec3 &ray_start, const kexVec3 &ray_end);
|
||||||
|
|
||||||
|
static TraceHit find_first_hit(TriangleMeshShape *shape, const kexVec3 &ray_start, const kexVec3 &ray_end);
|
||||||
|
|
||||||
struct Node
|
struct Node
|
||||||
{
|
{
|
||||||
Node() : left(-1), right(-1), element_index(-1) { }
|
Node() = default;
|
||||||
Node(const kexVec3 &aabb_min, const kexVec3 &aabb_max, int element_index) : aabb(aabb_min, aabb_max), left(-1), right(-1), element_index(element_index) { }
|
Node(const kexVec3 &aabb_min, const kexVec3 &aabb_max, int element_index) : aabb(aabb_min, aabb_max), element_index(element_index) { }
|
||||||
Node(const kexVec3 &aabb_min, const kexVec3 &aabb_max, int left, int right) : aabb(aabb_min, aabb_max), left(left), right(right), element_index(-1) { }
|
Node(const kexVec3 &aabb_min, const kexVec3 &aabb_max, int left, int right) : aabb(aabb_min, aabb_max), left(left), right(right) { }
|
||||||
|
|
||||||
kexBBox aabb;
|
kexBBox aabb;
|
||||||
int left;
|
int left = -1;
|
||||||
int right;
|
int right = -1;
|
||||||
int element_index;
|
int element_index = -1;
|
||||||
};
|
};
|
||||||
|
|
||||||
const kexVec3 *vertices;
|
const kexVec3 *vertices = nullptr;
|
||||||
const int num_vertices;
|
const int num_vertices = 0;
|
||||||
const unsigned int *elements;
|
const unsigned int *elements = nullptr;
|
||||||
int num_elements;
|
int num_elements = 0;
|
||||||
|
const int *surfaces = nullptr;
|
||||||
|
|
||||||
std::vector<Node> nodes;
|
std::vector<Node> nodes;
|
||||||
int root;
|
int root = -1;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
static float sweep(TriangleMeshShape *shape1, SphereShape *shape2, int a, const kexVec3 &target);
|
static float sweep(TriangleMeshShape *shape1, SphereShape *shape2, int a, const kexVec3 &target);
|
||||||
|
@ -78,6 +87,8 @@ private:
|
||||||
static bool find_any_hit(TriangleMeshShape *shape1, SphereShape *shape2, int a);
|
static bool find_any_hit(TriangleMeshShape *shape1, SphereShape *shape2, int a);
|
||||||
static bool find_any_hit(TriangleMeshShape *shape1, const kexVec3 &ray_start, const kexVec3 &ray_end, int a);
|
static bool find_any_hit(TriangleMeshShape *shape1, const kexVec3 &ray_start, const kexVec3 &ray_end, int a);
|
||||||
|
|
||||||
|
static void find_first_hit(TriangleMeshShape *shape1, const kexVec3 &ray_start, const kexVec3 &ray_end, int a, TraceHit *hit);
|
||||||
|
|
||||||
inline static bool overlap_bv_ray(TriangleMeshShape *shape, const kexVec3 &ray_start, const kexVec3 &ray_end, int a);
|
inline static bool overlap_bv_ray(TriangleMeshShape *shape, const kexVec3 &ray_start, const kexVec3 &ray_end, int a);
|
||||||
inline static float intersect_triangle_ray(TriangleMeshShape *shape, const kexVec3 &ray_start, const kexVec3 &ray_end, int a);
|
inline static float intersect_triangle_ray(TriangleMeshShape *shape, const kexVec3 &ray_start, const kexVec3 &ray_end, int a);
|
||||||
|
|
||||||
|
|
|
@ -42,8 +42,6 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
//#define EXPORT_TEXELS_OBJ
|
|
||||||
|
|
||||||
kexWorker lightmapWorker;
|
kexWorker lightmapWorker;
|
||||||
|
|
||||||
const kexVec3 kexLightmapBuilder::gridSize(64, 64, 128);
|
const kexVec3 kexLightmapBuilder::gridSize(64, 64, 128);
|
||||||
|
@ -223,22 +221,22 @@ kexBBox kexLightmapBuilder::GetBoundsFromSurface(const surface_t *surface)
|
||||||
// light if the surface that was traced is a sky
|
// light if the surface that was traced is a sky
|
||||||
//
|
//
|
||||||
|
|
||||||
bool kexLightmapBuilder::EmitFromCeiling(kexTrace &trace, const surface_t *surface, const kexVec3 &origin,
|
bool kexLightmapBuilder::EmitFromCeiling(kexTrace &trace, const surface_t *surface, const kexVec3 &origin, const kexVec3 &normal, kexVec3 &color)
|
||||||
const kexVec3 &normal, float *dist)
|
|
||||||
{
|
{
|
||||||
*dist = normal.Dot(map->GetSunDirection());
|
float dist = normal.Dot(map->GetSunDirection());
|
||||||
|
|
||||||
if(*dist <= 0)
|
if(dist <= 0)
|
||||||
{
|
{
|
||||||
// plane is not even facing the sunlight
|
// plane is not even facing the sunlight
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
trace.Trace(origin, origin + (map->GetSunDirection() * 32768));
|
trace.Trace(origin, origin + (map->GetSunDirection() * 32768.0f));
|
||||||
|
|
||||||
if(trace.fraction == 1 || trace.hitSurface == NULL)
|
if(trace.fraction == 1.0f)
|
||||||
{
|
{
|
||||||
// nothing was hit
|
// nothing was hit
|
||||||
|
//color.x += 1.0f;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,6 +246,8 @@ bool kexLightmapBuilder::EmitFromCeiling(kexTrace &trace, const surface_t *surfa
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
color += map->GetSunColor() * dist;
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,15 +336,8 @@ kexVec3 kexLightmapBuilder::LightTexelSample(kexTrace &trace, const kexVec3 &ori
|
||||||
if(surface->type != ST_CEILING && map->bSSectsVisibleToSky[surface->subSector - map->GLSubsectors])
|
if(surface->type != ST_CEILING && map->bSSectsVisibleToSky[surface->subSector - map->GLSubsectors])
|
||||||
{
|
{
|
||||||
// see if it's exposed to sunlight
|
// see if it's exposed to sunlight
|
||||||
if(EmitFromCeiling(trace, surface, origin, plane.Normal(), &dist))
|
if(EmitFromCeiling(trace, surface, origin, plane.Normal(), color))
|
||||||
{
|
|
||||||
dist = (dist * 4);
|
|
||||||
kexMath::Clamp(dist, 0, 1);
|
|
||||||
|
|
||||||
color += map->GetSunColor() * dist;
|
|
||||||
|
|
||||||
tracedTexels++;
|
tracedTexels++;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// trace against surface lights
|
// trace against surface lights
|
||||||
|
@ -504,13 +497,6 @@ void kexLightmapBuilder::TraceSurface(surface_t *surface)
|
||||||
|
|
||||||
normal = surface->plane.Normal();
|
normal = surface->plane.Normal();
|
||||||
|
|
||||||
// debugging stuff - used to help visualize where texels are positioned in the level
|
|
||||||
#ifdef EXPORT_TEXELS_OBJ
|
|
||||||
static int cnt = 0;
|
|
||||||
FILE *f = fopen(Va("texels_%02d.obj", cnt++), "w");
|
|
||||||
int indices = 0;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// start walking through each texel
|
// start walking through each texel
|
||||||
for(i = 0; i < sampleHeight; i++)
|
for(i = 0; i < sampleHeight; i++)
|
||||||
{
|
{
|
||||||
|
@ -522,13 +508,6 @@ void kexLightmapBuilder::TraceSurface(surface_t *surface)
|
||||||
(surface->lightmapSteps[0] * (float)j) +
|
(surface->lightmapSteps[0] * (float)j) +
|
||||||
(surface->lightmapSteps[1] * (float)i);
|
(surface->lightmapSteps[1] * (float)i);
|
||||||
|
|
||||||
// debugging stuff
|
|
||||||
#ifdef EXPORT_TEXELS_OBJ
|
|
||||||
ExportTexelsToObjFile(f, pos, indices);
|
|
||||||
indices += 8;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// accumulate color samples
|
|
||||||
kexVec3 c = LightTexelSample(trace, pos, surface);
|
kexVec3 c = LightTexelSample(trace, pos, surface);
|
||||||
|
|
||||||
// if nothing at all was traced and color is completely black
|
// if nothing at all was traced and color is completely black
|
||||||
|
@ -543,10 +522,6 @@ void kexLightmapBuilder::TraceSurface(surface_t *surface)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef EXPORT_TEXELS_OBJ
|
|
||||||
fclose(f);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// SVE redraws the scene for lightmaps, so for optimizations,
|
// SVE redraws the scene for lightmaps, so for optimizations,
|
||||||
// tell the engine to ignore this surface if completely black
|
// tell the engine to ignore this surface if completely black
|
||||||
if(bShouldLookupTexture == false)
|
if(bShouldLookupTexture == false)
|
||||||
|
|
|
@ -64,7 +64,7 @@ private:
|
||||||
kexBBox GetBoundsFromSurface(const surface_t *surface);
|
kexBBox GetBoundsFromSurface(const surface_t *surface);
|
||||||
kexVec3 LightTexelSample(kexTrace &trace, const kexVec3 &origin, surface_t *surface);
|
kexVec3 LightTexelSample(kexTrace &trace, const kexVec3 &origin, surface_t *surface);
|
||||||
kexVec3 LightCellSample(const int gridid, kexTrace &trace, const kexVec3 &origin, const MapSubsectorEx *sub);
|
kexVec3 LightCellSample(const int gridid, kexTrace &trace, const kexVec3 &origin, const MapSubsectorEx *sub);
|
||||||
bool EmitFromCeiling(kexTrace &trace, const surface_t *surface, const kexVec3 &origin, const kexVec3 &normal, float *dist);
|
bool EmitFromCeiling(kexTrace &trace, const surface_t *surface, const kexVec3 &origin, const kexVec3 &normal, kexVec3 &color);
|
||||||
void ExportTexelsToObjFile(FILE *f, const kexVec3 &org, int indices);
|
void ExportTexelsToObjFile(FILE *f, const kexVec3 &org, int indices);
|
||||||
void WriteBlock(FILE *f, const int i, const kexVec3 &org, int indices, kexBBox &box);
|
void WriteBlock(FILE *f, const int i, const kexVec3 &org, int indices, kexBBox &box);
|
||||||
|
|
||||||
|
|
|
@ -34,14 +34,8 @@
|
||||||
#include "mapdata.h"
|
#include "mapdata.h"
|
||||||
#include "surfaces.h"
|
#include "surfaces.h"
|
||||||
|
|
||||||
//#define EXPORT_OBJ
|
|
||||||
|
|
||||||
kexArray<surface_t*> surfaces;
|
kexArray<surface_t*> surfaces;
|
||||||
|
|
||||||
//
|
|
||||||
// Surface_AllocateFromSeg
|
|
||||||
//
|
|
||||||
|
|
||||||
static void Surface_AllocateFromSeg(FLevel &doomMap, MapSegGLEx *seg)
|
static void Surface_AllocateFromSeg(FLevel &doomMap, MapSegGLEx *seg)
|
||||||
{
|
{
|
||||||
IntSideDef *side;
|
IntSideDef *side;
|
||||||
|
@ -277,9 +271,21 @@ static void Surface_AllocateFromLeaf(FLevel &doomMap)
|
||||||
printf("\nLeaf surfaces: %i\n", surfaces.Length() - doomMap.NumGLSubsectors);
|
printf("\nLeaf surfaces: %i\n", surfaces.Length() - doomMap.NumGLSubsectors);
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
static bool IsDegenerate(const kexVec3 &v0, const kexVec3 &v1, const kexVec3 &v2)
|
||||||
// Surface_AllocateFromMap
|
{
|
||||||
//
|
// A degenerate triangle has a zero cross product for two of its sides.
|
||||||
|
float ax = v1.x - v0.x;
|
||||||
|
float ay = v1.y - v0.y;
|
||||||
|
float az = v1.z - v0.z;
|
||||||
|
float bx = v2.x - v0.x;
|
||||||
|
float by = v2.y - v0.y;
|
||||||
|
float bz = v2.z - v0.z;
|
||||||
|
float crossx = ay * bz - az * by;
|
||||||
|
float crossy = az * bx - ax * bz;
|
||||||
|
float crossz = ax * by - ay * bx;
|
||||||
|
float crosslengthsqr = crossx * crossx + crossy * crossy + crossz * crossz;
|
||||||
|
return crosslengthsqr <= 1.e-6f;
|
||||||
|
}
|
||||||
|
|
||||||
void Surface_AllocateFromMap(FLevel &doomMap)
|
void Surface_AllocateFromMap(FLevel &doomMap)
|
||||||
{
|
{
|
||||||
|
@ -301,61 +307,52 @@ void Surface_AllocateFromMap(FLevel &doomMap)
|
||||||
|
|
||||||
printf("\nSeg surfaces: %i\n", surfaces.Length());
|
printf("\nSeg surfaces: %i\n", surfaces.Length());
|
||||||
|
|
||||||
#ifdef EXPORT_OBJ
|
|
||||||
FILE *f = fopen("level.obj", "w");
|
|
||||||
int curLen = surfaces.Length();
|
|
||||||
for(unsigned int i = 0; i < surfaces.Length(); i++)
|
|
||||||
{
|
|
||||||
for(int j = 0; j < surfaces[i]->numVerts; j++)
|
|
||||||
{
|
|
||||||
fprintf(f, "v %f %f %f\n",
|
|
||||||
-surfaces[i]->verts[j].y / 256.0f,
|
|
||||||
surfaces[i]->verts[j].z / 256.0f,
|
|
||||||
-surfaces[i]->verts[j].x / 256.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
int tri;
|
|
||||||
|
|
||||||
for(unsigned int i = 0; i < surfaces.Length(); i++)
|
|
||||||
{
|
|
||||||
fprintf(f, "o surf%i_seg%i\n", i, i);
|
|
||||||
fprintf(f, "f %i %i %i\n", 0+(i*4)+1, 1+(i*4)+1, 2+(i*4)+1);
|
|
||||||
fprintf(f, "f %i %i %i\n", 1+(i*4)+1, 3+(i*4)+1, 2+(i*4)+1);
|
|
||||||
|
|
||||||
tri = 3+(i*4)+1;
|
|
||||||
}
|
|
||||||
|
|
||||||
tri++;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
Surface_AllocateFromLeaf(doomMap);
|
Surface_AllocateFromLeaf(doomMap);
|
||||||
|
|
||||||
printf("Surfaces total: %i\n\n", surfaces.Length());
|
printf("Surfaces total: %i\n\n", surfaces.Length());
|
||||||
|
|
||||||
#ifdef EXPORT_OBJ
|
printf("Building collision mesh..\n\n");
|
||||||
for(unsigned int i = curLen; i < surfaces.Length(); i++)
|
|
||||||
{
|
|
||||||
for(int j = 0; j < surfaces[i]->numVerts; j++)
|
|
||||||
{
|
|
||||||
fprintf(f, "v %f %f %f\n",
|
|
||||||
-surfaces[i]->verts[j].y / 256.0f,
|
|
||||||
surfaces[i]->verts[j].z / 256.0f,
|
|
||||||
-surfaces[i]->verts[j].x / 256.0f);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(unsigned int i = curLen; i < surfaces.Length(); i++)
|
for (unsigned int i = 0; i < surfaces.Length(); i++)
|
||||||
{
|
{
|
||||||
fprintf(f, "o surf%i_ssect%i\n", i, i - curLen);
|
const auto &s = surfaces[i];
|
||||||
fprintf(f, "f ");
|
int numVerts = s->numVerts;
|
||||||
for(int j = 0; j < surfaces[i]->numVerts; j++)
|
unsigned int pos = doomMap.MeshVertices.Size();
|
||||||
{
|
|
||||||
fprintf(f, "%i ", tri++);
|
|
||||||
}
|
|
||||||
fprintf(f, "\n");
|
|
||||||
}
|
|
||||||
|
|
||||||
fclose(f);
|
for (int j = 0; j < numVerts; j++)
|
||||||
#endif
|
doomMap.MeshVertices.Push(s->verts[j]);
|
||||||
|
|
||||||
|
if (s->type == ST_FLOOR || s->type == ST_CEILING)
|
||||||
|
{
|
||||||
|
for (int j = 2; j < numVerts; j++)
|
||||||
|
{
|
||||||
|
if (!IsDegenerate(s->verts[0], s->verts[j - 1], s->verts[j]))
|
||||||
|
{
|
||||||
|
doomMap.MeshElements.Push(pos);
|
||||||
|
doomMap.MeshElements.Push(pos + j - 1);
|
||||||
|
doomMap.MeshElements.Push(pos + j);
|
||||||
|
doomMap.MeshSurfaces.Push(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (s->type == ST_MIDDLESEG || s->type == ST_UPPERSEG || s->type == ST_LOWERSEG)
|
||||||
|
{
|
||||||
|
if (!IsDegenerate(s->verts[0], s->verts[1], s->verts[2]))
|
||||||
|
{
|
||||||
|
doomMap.MeshElements.Push(pos + 0);
|
||||||
|
doomMap.MeshElements.Push(pos + 1);
|
||||||
|
doomMap.MeshElements.Push(pos + 2);
|
||||||
|
doomMap.MeshSurfaces.Push(i);
|
||||||
|
}
|
||||||
|
if (!IsDegenerate(s->verts[1], s->verts[2], s->verts[3]))
|
||||||
|
{
|
||||||
|
doomMap.MeshElements.Push(pos + 1);
|
||||||
|
doomMap.MeshElements.Push(pos + 2);
|
||||||
|
doomMap.MeshElements.Push(pos + 3);
|
||||||
|
doomMap.MeshSurfaces.Push(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
doomMap.CollisionMesh.reset(new TriangleMeshShape(&doomMap.MeshVertices[0], doomMap.MeshVertices.Size(), &doomMap.MeshElements[0], doomMap.MeshElements.Size(), &doomMap.MeshSurfaces[0]));
|
||||||
}
|
}
|
||||||
|
|
|
@ -69,6 +69,15 @@ void kexTrace::Trace(const kexVec3 &startVec, const kexVec3 &endVec)
|
||||||
{
|
{
|
||||||
start = startVec;
|
start = startVec;
|
||||||
end = endVec;
|
end = endVec;
|
||||||
|
|
||||||
|
TraceHit hit = TriangleMeshShape::find_first_hit(map->CollisionMesh.get(), start, end);
|
||||||
|
fraction = hit.fraction;
|
||||||
|
if (fraction < 1.0f)
|
||||||
|
hitSurface = surfaces[hit.surface];
|
||||||
|
else
|
||||||
|
hitSurface = nullptr;
|
||||||
|
|
||||||
|
/*
|
||||||
dir = (end - start).Normalize();
|
dir = (end - start).Normalize();
|
||||||
hitNormal.Clear();
|
hitNormal.Clear();
|
||||||
hitVector.Clear();
|
hitVector.Clear();
|
||||||
|
@ -80,9 +89,11 @@ void kexTrace::Trace(const kexVec3 &startVec, const kexVec3 &endVec)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
TraceBSPNode(map->NumGLNodes - 1);
|
TraceBSPNode(map->NumGLNodes - 1);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if 0
|
||||||
//
|
//
|
||||||
// kexTrace::TraceSurface
|
// kexTrace::TraceSurface
|
||||||
//
|
//
|
||||||
|
@ -284,3 +295,4 @@ void kexTrace::TraceBSPNode(int num)
|
||||||
TraceBSPNode(node->children[side]);
|
TraceBSPNode(node->children[side]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
|
@ -40,17 +40,19 @@ public:
|
||||||
|
|
||||||
kexVec3 start;
|
kexVec3 start;
|
||||||
kexVec3 end;
|
kexVec3 end;
|
||||||
kexVec3 dir;
|
surface_t *hitSurface;
|
||||||
kexVec3 hitNormal;
|
float fraction;
|
||||||
kexVec3 hitVector;
|
|
||||||
surface_t *hitSurface;
|
|
||||||
float fraction;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
FLevel *map;
|
||||||
|
|
||||||
|
#if 0
|
||||||
|
kexVec3 dir;
|
||||||
|
kexVec3 hitNormal;
|
||||||
|
kexVec3 hitVector;
|
||||||
|
|
||||||
void TraceBSPNode(int num);
|
void TraceBSPNode(int num);
|
||||||
void TraceSubSector(int num);
|
void TraceSubSector(int num);
|
||||||
void TraceSurface(surface_t *surface);
|
void TraceSurface(surface_t *surface);
|
||||||
|
#endif
|
||||||
FLevel *map;
|
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
Loading…
Reference in a new issue