Browse Source

Added geometry basic functions.

TODO : second pass on coding-style, and some tweak & usage modification.
legacy
Benjamin ‘Touky’ Huet touky 12 years ago
parent
commit
3d56a23a55
6 changed files with 2037 additions and 1665 deletions
  1. +2
    -0
      src/Makefile.am
  2. +1
    -0
      src/core.h
  3. +55
    -0
      src/lol/math/geometry.h
  4. +2
    -0
      src/lolcore.vcxproj
  5. +1671
    -1665
      src/lolcore.vcxproj.filters
  6. +306
    -0
      src/math/geometry.cpp

+ 2
- 0
src/Makefile.am View File

@@ -21,6 +21,7 @@ liblol_a_SOURCES = \
lol/base/map.h \
lol/math/vector.h lol/math/half.h lol/math/real.h lol/math/remez.h \
lol/math/math.h \
lol/math/geometry.h \
lol/image/color.h \
\
generated/location.hh generated/position.hh generated/stack.hh \
@@ -46,6 +47,7 @@ liblol_a_SOURCES = \
thread/threadbase.h thread/thread.h \
\
math/vector.cpp math/real.cpp math/half.cpp math/trig.cpp \
math/geometry.cpp \
\
input/input.cpp input/input.h \
input/keyboard.cpp input/keyboard.h \


+ 1
- 0
src/core.h View File

@@ -86,6 +86,7 @@ static inline int isnan(float f)
#include <lol/math/half.h>
#include <lol/math/real.h>
#include <lol/math/vector.h>
#include <lol/math/geometry.h>

#include <lol/image/color.h>



+ 55
- 0
src/lol/math/geometry.h View File

@@ -0,0 +1,55 @@
//
// Lol Engine
//
// Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
// (c) 2010-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
//

//
// Various geometry functions
// -----------------------
//

#if !defined __LOL_GEOMETRY_GEOMETRY_H__
#define __LOL_GEOMETRY_GEOMETRY_H__

#include <cmath>
#include <cstdio>
#include <algorithm>

#include <stdint.h>

#define CSG_EPSILON 0.0001

namespace lol
{
bool TriangleIsectTriangle(vec3 const &v00, vec3 const &v01, vec3 const &v02,
vec3 const &v10, vec3 const &v11, vec3 const &v12,
vec3 &iP00, vec3 &iP10);
bool RayIsectTriangleSide(vec3 const &v0, vec3 const &v1, vec3 const &v2,
vec3 const &iP0, vec3 const &iP1,
vec3 &iV0, int &iIdx0, vec3 &iV1, int &iIdx1);
bool RayIsectTriangle(vec3 const &rayP, vec3 const &rayD,
vec3 const &triV0, vec3 const &triV1, vec3 const &triV2,
vec3 &vi);
#define RAY_ISECT_NOTHING 0
#define RAY_ISECT_ALL 1
#define RAY_ISECT_NONE 2
#define RAY_ISECT_P0 3
#define RAY_ISECT_P1 4
int RayIsectRay(vec3 const &rayP00, vec3 const &rayP01,
vec3 const &rayP10, vec3 const &rayP11,
vec3 &vIsec);
vec3 ProjPointOnPlane(vec3 const &point, vec3 const &planeP, vec3 const &planeN);
bool RayIsectPlane(vec3 const &rayP0, vec3 const &rayP1,
vec3 const &planeP, vec3 const &planeN,
vec3 &vIsec, bool test_line_only = false);

} /* namespace lol */

#endif // __LOL_GEOMETRY_GEOMETRY_H__


+ 2
- 0
src/lolcore.vcxproj View File

@@ -273,6 +273,7 @@
<ClCompile Include="layer.cpp" />
<ClCompile Include="log.cpp" />
<ClCompile Include="map.cpp" />
<ClCompile Include="math\geometry.cpp" />
<ClCompile Include="math\half.cpp" />
<ClCompile Include="math\real.cpp" />
<ClCompile Include="math\trig.cpp" />
@@ -590,6 +591,7 @@
<ClInclude Include="lol\base\types.h" />
<ClInclude Include="lol\debug.h" />
<ClInclude Include="lol\image\color.h" />
<ClInclude Include="lol\math\geometry.h" />
<ClInclude Include="lol\math\half.h" />
<ClInclude Include="lol\math\math.h" />
<ClInclude Include="lol\math\real.h" />


+ 1671
- 1665
src/lolcore.vcxproj.filters
File diff suppressed because it is too large
View File


+ 306
- 0
src/math/geometry.cpp View File

@@ -0,0 +1,306 @@
//
// Lol Engine
//
// Copyright: (c) 2010-2013 Sam Hocevar <sam@hocevar.net>
// (c) 2010-2013 Benjamin "Touky" Huet <huet.benjamin@gmail.com>
// This program is free software; you can redistribute it and/or
// modify it under the terms of the Do What The Fuck You Want To
// Public License, Version 2, as published by Sam Hocevar. See
// http://www.wtfpl.net/ for more details.
//

#if defined HAVE_CONFIG_H
# include "config.h"
#endif

#if defined _XBOX
# define _USE_MATH_DEFINES /* for M_PI */
# include <xtl.h>
# undef near /* Fuck Microsoft */
# undef far /* Fuck Microsoft again */
#elif defined _WIN32
# define _USE_MATH_DEFINES /* for M_PI */
# define WIN32_LEAN_AND_MEAN
# include <windows.h>
# undef near /* Fuck Microsoft */
# undef far /* Fuck Microsoft again */
#endif

#include <cstdlib> /* free() */
#include <cstring> /* strdup() */

#include <ostream> /* std::ostream */

#include "core.h"

using namespace std;

namespace lol
{
//Projects Point on Plane : Normal must be given normalized. returns point on plane.
vec3 ProjPointOnPlane(vec3 const &point, vec3 const &planeP, vec3 const &planeN)
{
vec3 o2p = point - planeP;
float d = -dot(o2p, planeN);
return point + d * planeN;
}

//gets the dist from a Point to a Plane : Normal must be given normalized. returns distance.
float PointDistToPlane(vec3 const &point, vec3 const &planeP, vec3 const &planeN)
{
vec3 o2p = point - planeP;
return abs(dot(o2p, planeN));
}

// Line/triangle : sets vIsec as the intersection point & return true if ok.
bool RayIsectTriangle(vec3 const &rayP, vec3 const &rayD,
vec3 const &triV0, vec3 const &triV1, vec3 const &triV2,
vec3 &vIsec)
{
vec3 v01, v02, h, v0P, q;
float a, f, triU, triV;
//
v01 = triV1 - triV0;
v02 = triV2 - triV0;

h = cross(rayD, v02);
a = dot(v01, h);

//rayDir is coplanar to the triangle, exit.
if (a > -CSG_EPSILON && a < CSG_EPSILON)
return false;

f = 1 / a;
v0P = rayP - triV0;
triU = f * (dot(v0P, h));

//point is supposed to have an U on the segment v01
if (triU < -CSG_EPSILON || triU > 1.0)
return false;

q = cross(v0P, v01);
triV = f * dot(rayD, q);

//point is not in the triangle
if (triV < -CSG_EPSILON || triU + triV > 1.0)
return false;

// at this stage we can compute t to find out where
// the intersection point is on the line
float t = f * dot(v02, q);

if (t > CSG_EPSILON) // ray intersection
{
vIsec = triV0 + v01 * triU + v02 * triV;
return true;
}
else // this means that there is a line intersection
// but not a ray intersection
return false;
}

// Triangle/Triangle
bool TriangleIsectTriangle(vec3 const &v00, vec3 const &v01, vec3 const &v02, //triangle 0
vec3 const &v10, vec3 const &v11, vec3 const &v12, //triangle 1
vec3 &iP00, vec3 &iP10) //triangle intersection, iPx means gives the actual intersection points.
{
vec3 isec[2] = { vec3(0, 0, 0), vec3(0, 0, 0) };
vec3 triV[6] = { v00, v01, v02,
v10, v11, v12 };
vec3 triD[6] = { v01 - v00, v02 - v01, v00 - v02,
v11 - v10, v12 - v11, v10 - v12 };
int isecIdx = 0;
vec3 vIsec(0);

//Check the normal before doing any other calculations
vec3 plane_norm[2] = { cross(normalize(triD[0]), normalize(triD[1])),
cross(normalize(triD[3]), normalize(triD[4])) };
if (abs(dot(plane_norm[0], plane_norm[1])) == 1.0f)
return false;

#if 0
//Precheck to verify if two point of one of the tri-A are on tri-B, and vice versa.
int zero_dist[2] = { 0, 0 };
for (int i = 0; i < 3; i++)
{
if (PointDistToPlane(triV[i], triV[3], plane_norm[1]) < CSG_EPSILON)
zero_dist[0]++;
if (PointDistToPlane(triV[i + 3], triV[0], plane_norm[0]) < CSG_EPSILON)
zero_dist[1]++;
}

if (zero_dist[0] >= 2 || zero_dist[0] >= 2)
return false;
#endif

//We first need to find two points intersecting, no matter on which triangle.
for (int i = 0; i < 2 && isecIdx < 2; i++)
{
int found_isec = -1;
for (int j = 0; j < 3 && isecIdx < 2; j++)
{
int pIdx = j + i * 3;
int tIdx = (1 - i) * 3;
if (RayIsectTriangle(triV[pIdx], triD[pIdx],
triV[tIdx + 0], triV[tIdx + 1], triV[tIdx + 2],
isec[isecIdx]))
{
#if 1 //if the point is near one the given entry, consider it as being the same point.
for (int k = 0; k < 6; k++)
{
if (length(isec[isecIdx] - triV[k]) < CSG_EPSILON)
{
isec[isecIdx] = triV[k];
break;
}
}
#endif

//Automatic pass on the first intersection
if (isecIdx == 0 ||
//If we have already found an intersection, pass if it's on this triangle.
/*found_isec == i ||*/
//if it's the second intersection, we need it to be different from the first one.
(isecIdx == 1 && length(isec[0] - isec[1]) > CSG_EPSILON))
{
found_isec = i;
isecIdx++;
}
}
}
}

if (isecIdx >= 2)
{
iP00 = isec[0];
iP10 = isec[1];
return true;
}
return false;
}

//Ray/Line : returns one of the RAY_ISECT_* defines.
int RayIsectRay(vec3 const &rayP00, vec3 const &rayP01,
vec3 const &rayP10, vec3 const &rayP11,
vec3 &vIsec)
{
vec3 rayD0 = rayP01 - rayP00;
float rayS0 = length(rayD0);
vec3 rayD0N = normalize(rayD0);

vec3 rayD1 = rayP11 - rayP10;
float rayS1 = length(rayD1);
vec3 rayD1N = normalize(rayD1);

vec3 rayP0P1 = rayP10 - rayP00;
vec3 c01 = cross(rayD0N, rayD1N);
float crs01S = length(c01);

if (crs01S > -CSG_EPSILON && crs01S < CSG_EPSILON)
return 0;

mat3 m0 = mat3(rayP0P1, rayD1N, c01);
float t0 = determinant(m0) / (crs01S * crs01S);
vec3 isec0 = rayP00 + rayD0N * t0;

mat3 m1 = mat3(rayP0P1, rayD0N, c01);
float t1 = determinant(m1) / (crs01S * crs01S);
vec3 isec1 = rayP10 + rayD1N * t1;

if (sqlength(isec0 - isec1) < CSG_EPSILON) //ray intersection
{
vIsec = (isec0 + isec0) * .5f;
float d0 = (length(rayP01 - vIsec) < CSG_EPSILON || length(rayP00 - vIsec) < CSG_EPSILON)?
(-1.0f):
(dot(rayP00 - vIsec, rayP01 - vIsec));
float d1 = (length(rayP10 - vIsec) < CSG_EPSILON || length(rayP11 - vIsec) < CSG_EPSILON)?
(-1.0f):
(dot(rayP10 - vIsec, rayP11 - vIsec));

//if the dot is negative, your point is in each ray, so say OK.
if (d0 < .0f && d1 < .0f)
return RAY_ISECT_ALL;
if (d0 < .0f)
return RAY_ISECT_P0;
if (d1 < .0f)
return RAY_ISECT_P1;
return RAY_ISECT_NONE;
}
else // this means that there is a line intersection
// but not a ray intersection
return RAY_ISECT_NOTHING;
}

//Ray/Plane : Normal must be given normalized. returns 1 if succeeded.
bool RayIsectPlane(vec3 const &rayP0, vec3 const &rayP1,
vec3 const &planeP, vec3 const &planeN,
vec3 &vIsec, bool test_line_only)
{
vec3 ray_dir = rayP1 - rayP0;
float d = dot(ray_dir, planeN);

if (d > -CSG_EPSILON && d < CSG_EPSILON)
return false;

vec3 o2p1 = rayP1 - planeP;
vec3 o2p0 = rayP0 - planeP;

if (!test_line_only)
{
d = dot(o2p1, planeN);
d *= dot(o2p0, planeN);

//point are on the same side, so ray can intersect.
if (d > .0f)
return false;
}

float t = (dot(ProjPointOnPlane(rayP0, planeP, planeN) - rayP0, planeN)) / dot(ray_dir, planeN);

if (!test_line_only && (t < -CSG_EPSILON || t > 1.0f))
return false;

vIsec = rayP0 + t * ray_dir;
return true;
}

//used to find the intersecting points between a triangle side and a coplanar line.
bool RayIsectTriangleSide(vec3 const &v0, vec3 const &v1, vec3 const &v2,
vec3 const &iP0, vec3 const &iP1,
vec3 &iV0, int &iIdx0, vec3 &iV1, int &iIdx1)
{
vec3 isecV[2] = { vec3(.0f), vec3(.0f) };
int isecI[2] = { -1, -1 };

vec3 triV[3] = { v0, v1, v2 };
int isecIdx = 0;
vec3 vIsec(0);

//Two points given, so we test each triangle side to find the intersect
isecIdx = 0;
for (int j = 0; j < 3 && isecIdx < 2; j++)
{
int Result = RayIsectRay(triV[j], triV[(j + 1) % 3], iP0, iP1, vIsec);
if (Result == RAY_ISECT_P0 || Result == RAY_ISECT_ALL)
{
isecV[isecIdx] = vIsec;
isecI[isecIdx] = j;
isecIdx++;
}
}

if (isecIdx < 2)
return false;

//We send the infos back to the parent.
//TODO : that can be better than this horrible thing.
iV0 = isecV[0];
iV1 = isecV[1];
iIdx0 = isecI[0];
iIdx1 = isecI[1];
return true;
}

} /* namespace lol */


Loading…
Cancel
Save