11 changed files with 6075 additions and 85 deletions
-
2src/5threed/Image.h
-
163src/5threed/Raster.cc
-
15src/5threed/Raster.h
-
5418src/5threed/common.h
-
159src/5threed/struct/common.h
-
175src/5threed/struct/plane.h
-
87src/5threed/struct/tfrustum.h
-
6src/5threed/struct/tmat4x4.h
-
67src/5threed/struct/tvec3.h
-
53src/5threed/struct/tvec4.h
-
15src/5threed/threed.cc
5418
src/5threed/common.h
File diff suppressed because it is too large
View File
File diff suppressed because it is too large
View File
@ -0,0 +1,159 @@ |
|||
/* |
|||
* To change this license header, choose License Headers in Project Properties. |
|||
* To change this template file, choose Tools | Templates |
|||
* and open the template in the editor. |
|||
*/ |
|||
|
|||
/* |
|||
* File: common.h |
|||
* Author: Blobt |
|||
* |
|||
* Created on October 5, 2019, 4:55 PM |
|||
*/ |
|||
|
|||
#ifndef COMMON_H |
|||
#define COMMON_H |
|||
|
|||
#include <assert.h> |
|||
#include <cstddef> |
|||
#include <stdlib.h> |
|||
#include <cmath> |
|||
#include "Rgba.h" |
|||
#include "struct/tvec2.h" |
|||
#include "struct/tvec3.h" |
|||
#include "struct/tmat3x3.h" |
|||
#include "struct/tvec4.h" |
|||
#include "struct/tmat4x4.h" |
|||
#include "struct/tfrustum.h" |
|||
|
|||
#define die(m) do { perror(m); exit(EXIT_FAILURE); } while(0) |
|||
#define def2rad(theta) (0.01745329251994329 * (theta)) //每个角度所对应的弧度 |
|||
|
|||
typedef tvec2<float> float2; |
|||
typedef tvec2<int> int2; |
|||
typedef tvec3<float> float3; |
|||
typedef tvec4<float> float4; |
|||
typedef unsigned char byte; |
|||
typedef tmat3x3<float> matrix3; |
|||
typedef tmat4x4<float> matrix4; |
|||
typedef tfrustum<float> Frustum; |
|||
|
|||
template<class T> inline T tmin(T a, T b) { |
|||
return a < b ? a : b; |
|||
} |
|||
|
|||
template<class T> inline T tmax(T a, T b) { |
|||
return a > b ? a : b; |
|||
} |
|||
|
|||
inline Rgba colorLerp(const Rgba& color1, const Rgba& color2, float step) { |
|||
Rgba ret; |
|||
|
|||
ret._r = (unsigned char) color1._r + step * (color2._r - color1._r); |
|||
ret._g = (unsigned char) color1._g + step * (color2._g - color1._g); |
|||
ret._b = (unsigned char) color1._b + step * (color2._b - color1._b); |
|||
ret._a = (unsigned char) color1._a + step * (color2._a - color1._a); |
|||
|
|||
return ret; |
|||
} |
|||
|
|||
inline float2 uvLerp(const float2& uv1, const float2& uv2, float step) { |
|||
|
|||
if (step < 0 || step > 1) { |
|||
printf("step : %f\n", step); |
|||
die("step must more than zero and less than 1"); |
|||
} |
|||
|
|||
float2 ret; |
|||
|
|||
ret.x = (float) uv1.x + (uv2.x - uv1.x) * step; |
|||
ret.y = (float) uv1.y + (uv2.y - uv1.y) * step; |
|||
|
|||
return ret; |
|||
} |
|||
|
|||
template <typename T> |
|||
tvec3<T> cross(tvec3<T> const & x, tvec3<T> const & y) { |
|||
return tvec3<T> |
|||
( |
|||
x.y * y.z - y.y * x.z, |
|||
x.z * y.x - y.z * x.x, |
|||
x.x * y.y - y.x * x.y |
|||
); |
|||
} |
|||
|
|||
template <typename T> |
|||
typename tvec3<T>::value_type dot(tvec3<T> const & x, tvec3<T> const & y) { |
|||
return x.x * y.x + x.y * y.y + x.z * y.z; |
|||
} |
|||
|
|||
template <typename T> |
|||
T inversesqrt(T x) { |
|||
return T(1) / sqrt(x); |
|||
} |
|||
|
|||
template <typename T> |
|||
tvec2<T> normalize(tvec2<T> const & x) { |
|||
typename tvec2<T>::value_type sqr = x.x * x.x + x.y * x.y; |
|||
return x * inversesqrt(sqr); |
|||
} |
|||
|
|||
template <typename T> |
|||
tvec3<T> normalize(tvec3<T> const & x) { |
|||
typename tvec3<T>::value_type sqr = x.x * x.x + x.y * x.y + x.z * x.z; |
|||
return x * inversesqrt(sqr); |
|||
} |
|||
|
|||
template <typename T> |
|||
tvec4<T> normalize(tvec4<T> const & x) { |
|||
typename tvec4<T>::value_type sqr = x.x * x.x + x.y * x.y + x.z * x.z + x.w * x.w; |
|||
return x * inversesqrt(sqr); |
|||
} |
|||
|
|||
template <typename valType> |
|||
tmat4x4<valType> perspective(valType fovy, valType aspect, valType zNear, valType zFar) { |
|||
valType range = tan(fovy * valType(DEG2RAD(0.5))) * zNear; |
|||
valType left = -range * aspect; |
|||
valType right = range * aspect; |
|||
valType bottom = -range; |
|||
valType top = range; |
|||
|
|||
tmat4x4<valType> res(valType(0)); |
|||
res[0][0] = (valType(2) * zNear) / (right - left); |
|||
res[1][1] = (valType(2) * zNear) / (top - bottom); |
|||
res[2][2] = -(zFar + zNear) / (zFar - zNear); |
|||
res[2][3] = -valType(1); |
|||
res[3][2] = -(valType(2) * zFar * zNear) / (zFar - zNear); |
|||
return res; |
|||
} |
|||
|
|||
template <typename T> |
|||
tmat4x4<T> lookAt |
|||
( |
|||
tvec3<T> const & eye, |
|||
tvec3<T> const & center, |
|||
tvec3<T> const & up |
|||
) { |
|||
tvec3<T> f = normalize(center - eye); |
|||
tvec3<T> u = normalize(up); |
|||
tvec3<T> s = normalize(cross(f, u)); |
|||
u = cross(s, f); |
|||
|
|||
tmat4x4<T> res(1); |
|||
res[0][0] = s.x; |
|||
res[1][0] = s.y; |
|||
res[2][0] = s.z; |
|||
res[0][1] = u.x; |
|||
res[1][1] = u.y; |
|||
res[2][1] = u.z; |
|||
res[0][2] = -f.x; |
|||
res[1][2] = -f.y; |
|||
res[2][2] = -f.z; |
|||
res[3][0] = -dot(s, eye); |
|||
res[3][1] = -dot(u, eye); |
|||
res[3][2] = dot(f, eye); |
|||
return res; |
|||
} |
|||
|
|||
#endif /* COMMON_H */ |
|||
|
@ -0,0 +1,175 @@ |
|||
/* |
|||
* To change this license header, choose License Headers in Project Properties. |
|||
* To change this template file, choose Tools | Templates |
|||
* and open the template in the editor. |
|||
*/ |
|||
|
|||
/* |
|||
* File: plane.h |
|||
* Author: Blobt |
|||
* |
|||
* Created on February 23, 2020, 11:33 AM |
|||
*/ |
|||
|
|||
#ifndef PLANE_H |
|||
#define PLANE_H |
|||
#include "../common.h" |
|||
|
|||
template<class T> |
|||
class Plane { |
|||
public: |
|||
tvec3<T> _normal; |
|||
T _distance; |
|||
public: |
|||
|
|||
Plane() { |
|||
_normal = tvec3<T>(0, 0, 0); |
|||
_distance = 0.0f; |
|||
} |
|||
|
|||
Plane(const Plane& right) { |
|||
_normal = right._normal; |
|||
_distance = right._distance; |
|||
} |
|||
|
|||
/** Construct a plane through a normal, and a distance to move the plane along the normal.*/ |
|||
Plane(const tvec3<T>& rkNormal, T fConstant) { |
|||
_normal = rkNormal; |
|||
_distance = -fConstant; |
|||
} |
|||
|
|||
/** Construct a plane using the 4 constants directly **/ |
|||
Plane(T x, T y, T z, T o) { |
|||
_normal = tvec3<T>(x, y, z); |
|||
T invLen = 1.0f / (_normal).length(); |
|||
_normal *= invLen; |
|||
_distance = o * invLen; |
|||
} |
|||
|
|||
Plane(const tvec3<T>& rkNormal, const tvec3<T>& rkPoint) { |
|||
redefine(rkNormal, rkPoint); |
|||
} |
|||
|
|||
Plane(const tvec3<T>& rkPoint0, const tvec3<T>& rkPoint1, const tvec3<T>& rkPoint2) { |
|||
redefine(rkPoint0, rkPoint1, rkPoint2); |
|||
} |
|||
|
|||
/** |
|||
* ����ľ��� |
|||
*/ |
|||
float distance(const tvec3<T> &pos) const { |
|||
return dot(_normal, pos) + _distance; |
|||
} |
|||
|
|||
/** The "positive side" of the plane is the half space to which the |
|||
plane normal points. The "negative side" is the other half |
|||
space. The flag "no side" indicates the plane itself. |
|||
*/ |
|||
enum Side { |
|||
NO_SIDE, |
|||
POSITIVE_SIDE, |
|||
NEGATIVE_SIDE, |
|||
BOTH_SIDE |
|||
}; |
|||
|
|||
Side getSide(const tvec3<T>& rkPoint) const { |
|||
float fDistance = getDistance(rkPoint); |
|||
|
|||
if (fDistance < 0.0) |
|||
return Plane::NEGATIVE_SIDE; |
|||
|
|||
if (fDistance > 0.0) |
|||
return Plane::POSITIVE_SIDE; |
|||
|
|||
return Plane::NO_SIDE; |
|||
} |
|||
|
|||
Side getSide(const tvec3<T>& centre, const tvec3<T>& halfSize) const { |
|||
// Calculate the distance between box centre and the plane |
|||
float dist = getDistance(centre); |
|||
|
|||
// Calculate the maximise allows absolute distance for |
|||
// the distance between box centre and plane |
|||
float maxAbsDist = _normal.absDot(halfSize); |
|||
|
|||
if (dist < -maxAbsDist) |
|||
return Plane::NEGATIVE_SIDE; |
|||
|
|||
if (dist > +maxAbsDist) |
|||
return Plane::POSITIVE_SIDE; |
|||
|
|||
return Plane::BOTH_SIDE; |
|||
} |
|||
|
|||
float getDistance(const tvec3<T>& rkPoint) const { |
|||
return _normal.dot(rkPoint) + _distance; |
|||
} |
|||
|
|||
void redefine(const tvec3<T>& rkPoint0, const tvec3<T>& rkPoint1, |
|||
const tvec3<T>& rkPoint2) { |
|||
tvec3<T> kEdge1 = rkPoint1 - rkPoint0; |
|||
tvec3<T> kEdge2 = rkPoint2 - rkPoint0; |
|||
_normal = cross(kEdge1, kEdge2); |
|||
_normal.normalise(); |
|||
_distance = -dot(_normal, rkPoint0); |
|||
} |
|||
|
|||
/** Redefine this plane based on a normal and a point. */ |
|||
void redefine(const tvec3<T>& rkNormal, const tvec3<T>& rkPoint) { |
|||
_normal = rkNormal; |
|||
_distance = -dot(rkNormal, rkPoint); |
|||
} |
|||
|
|||
|
|||
// tvec3<T> projectVector(const tvec3<T>& p) const |
|||
// { |
|||
// matrix3 xform; |
|||
// xform[0][0] = 1.0f - _normal.x * _normal.x; |
|||
// xform[0][1] = -_normal.x * _normal.y; |
|||
// xform[0][2] = -_normal.x * _normal.z; |
|||
// xform[1][0] = -_normal.y * _normal.x; |
|||
// xform[1][1] = 1.0f - _normal.y * _normal.y; |
|||
// xform[1][2] = -_normal.y * _normal.z; |
|||
// xform[2][0] = -_normal.z * _normal.x; |
|||
// xform[2][1] = -_normal.z * _normal.y; |
|||
// xform[2][2] = 1.0f - _normal.z * _normal.z; |
|||
// return xform * p; |
|||
// } |
|||
|
|||
/** Normalises the plane. |
|||
@remarks |
|||
This method normalises the plane's normal and the length scale of d |
|||
is as well. |
|||
@note |
|||
This function will not crash for zero-sized vectors, but there |
|||
will be no changes made to their components. |
|||
@returns The previous length of the plane's normal. |
|||
*/ |
|||
float normalise(void) { |
|||
float fLength = _normal.length(); |
|||
|
|||
// Will also work for zero-sized vectors, but will change nothing |
|||
if (fLength > 1e-08f) { |
|||
float fInvLength = 1.0f / fLength; |
|||
_normal *= fInvLength; |
|||
_distance *= fInvLength; |
|||
} |
|||
|
|||
return fLength; |
|||
} |
|||
|
|||
|
|||
|
|||
/// Comparison operator |
|||
|
|||
bool operator==(const Plane& right) const { |
|||
return (right._distance == _distance && right._normal == _normal); |
|||
} |
|||
|
|||
bool operator!=(const Plane& right) const { |
|||
return (right._distance != _distance && right._normal != _normal); |
|||
} |
|||
}; |
|||
|
|||
#endif /* PLANE_H */ |
|||
|
@ -0,0 +1,87 @@ |
|||
/* |
|||
* To change this license header, choose License Headers in Project Properties. |
|||
* To change this template file, choose Tools | Templates |
|||
* and open the template in the editor. |
|||
*/ |
|||
|
|||
/* |
|||
* File: tfrustum.h |
|||
* Author: Blobt |
|||
* |
|||
* Created on February 23, 2020, 11:22 AM |
|||
*/ |
|||
|
|||
#ifndef TFRUSTUM_H |
|||
#define TFRUSTUM_H |
|||
#include "../common.h" |
|||
#include "plane.h" |
|||
|
|||
template<class T> |
|||
class tfrustum { |
|||
public: |
|||
|
|||
enum { |
|||
FRUSTUM_LEFT = 0, |
|||
FRUSTUM_RIGHT = 1, |
|||
FRUSTUM_TOP = 2, |
|||
FRUSTUM_BOTTOM = 3, |
|||
FRUSTUM_FAR = 4, |
|||
FRUSTUM_NEAR = 5, |
|||
}; |
|||
public: |
|||
|
|||
/** |
|||
* project * view |
|||
*/ |
|||
void loadFrustum(const tmat4x4<T> &mvp) { |
|||
const T* dataPtr = mvp.data(); |
|||
_planes[FRUSTUM_LEFT ] = Plane<T>(dataPtr[12] - dataPtr[0], dataPtr[13] - dataPtr[1], dataPtr[14] - dataPtr[2], dataPtr[15] - dataPtr[3]); |
|||
_planes[FRUSTUM_RIGHT ] = Plane<T>(dataPtr[12] + dataPtr[0], dataPtr[13] + dataPtr[1], dataPtr[14] + dataPtr[2], dataPtr[15] + dataPtr[3]); |
|||
|
|||
_planes[FRUSTUM_TOP ] = Plane<T>(dataPtr[12] - dataPtr[4], dataPtr[13] - dataPtr[5], dataPtr[14] - dataPtr[6], dataPtr[15] - dataPtr[7]); |
|||
_planes[FRUSTUM_BOTTOM] = Plane<T>(dataPtr[12] + dataPtr[4], dataPtr[13] + dataPtr[5], dataPtr[14] + dataPtr[6], dataPtr[15] + dataPtr[7]); |
|||
|
|||
_planes[FRUSTUM_FAR ] = Plane<T>(dataPtr[12] - dataPtr[8], dataPtr[13] - dataPtr[9], dataPtr[14] - dataPtr[10], dataPtr[15] - dataPtr[11]); |
|||
_planes[FRUSTUM_NEAR ] = Plane<T>(dataPtr[12] + dataPtr[8], dataPtr[13] + dataPtr[9], dataPtr[14] + dataPtr[10], dataPtr[15] + dataPtr[11]); |
|||
} |
|||
|
|||
bool pointInFrustum(const tvec3<T> &pos) const { |
|||
for (int i = 0; i < 6; i++) { |
|||
if (_planes[i].distance(pos) <= 0) |
|||
return false; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
bool sphereInFrustum(const tvec3<T> &pos, const float radius) const { |
|||
for (int i = 0; i < 6; i++) { |
|||
if (_planes[i].distance(pos) <= -radius) |
|||
return false; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
bool cubeInFrustum(T minX, T maxX, T minY, T maxY, T minZ, T maxZ) const { |
|||
for (int i = 0; i < 6; i++) { |
|||
if (_planes[i].distance(tvec3<T>(minX, minY, minZ)) > 0) continue; |
|||
if (_planes[i].distance(tvec3<T>(minX, minY, maxZ)) > 0) continue; |
|||
if (_planes[i].distance(tvec3<T>(minX, maxY, minZ)) > 0) continue; |
|||
if (_planes[i].distance(tvec3<T>(minX, maxY, maxZ)) > 0) continue; |
|||
if (_planes[i].distance(tvec3<T>(maxX, minY, minZ)) > 0) continue; |
|||
if (_planes[i].distance(tvec3<T>(maxX, minY, maxZ)) > 0) continue; |
|||
if (_planes[i].distance(tvec3<T>(maxX, maxY, minZ)) > 0) continue; |
|||
if (_planes[i].distance(tvec3<T>(maxX, maxY, maxZ)) > 0) continue; |
|||
return false; |
|||
} |
|||
return true; |
|||
} |
|||
|
|||
const Plane<T> &getPlane(const int plane) const { |
|||
return _planes[plane]; |
|||
} |
|||
protected: |
|||
Plane<T> _planes[6]; |
|||
}; |
|||
|
|||
#endif /* TFRUSTUM_H */ |
|||
|
Write
Preview
Loading…
Cancel
Save
Reference in new issue