Merge changes from internal branch.
- Add frustum class and bezier evaluation functions. - Add component accessors to vector. - Add matrix constructors. - Fix errors in sparse solvers. - Better robust orthogonalization. - Fix montecarlo distribution.
This commit is contained in:
parent
e5ae0c0e20
commit
b4f17b968a
|
@ -27,7 +27,8 @@ void Basis::orthonormalize(float epsilon /*= NV_EPSILON*/)
|
||||||
tangent -= normal * dot(normal, tangent);
|
tangent -= normal * dot(normal, tangent);
|
||||||
tangent = ::normalize(tangent, epsilon);
|
tangent = ::normalize(tangent, epsilon);
|
||||||
|
|
||||||
bitangent -= normal * dot(normal, bitangent) + tangent * dot(tangent, bitangent);
|
bitangent -= normal * dot(normal, bitangent);
|
||||||
|
bitangent -= tangent * dot(tangent, bitangent);
|
||||||
bitangent = ::normalize(bitangent, epsilon);
|
bitangent = ::normalize(bitangent, epsilon);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,7 +92,15 @@ void Basis::robustOrthonormalize(float epsilon /*= NV_EPSILON*/)
|
||||||
tangent = nv::normalize(tangent);
|
tangent = nv::normalize(tangent);
|
||||||
bitangent = nv::normalize(bitangent);
|
bitangent = nv::normalize(bitangent);
|
||||||
|
|
||||||
Vector3 bisector = nv::normalize(tangent + bitangent);
|
Vector3 bisector;
|
||||||
|
if (length(tangent + bitangent) < epsilon)
|
||||||
|
{
|
||||||
|
bisector = tangent;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
bisector = nv::normalize(tangent + bitangent);
|
||||||
|
}
|
||||||
Vector3 axis = cross(bisector, normal);
|
Vector3 axis = cross(bisector, normal);
|
||||||
|
|
||||||
nvDebugCheck(isNormalized(axis, epsilon));
|
nvDebugCheck(isNormalized(axis, epsilon));
|
||||||
|
|
|
@ -12,8 +12,10 @@ namespace nv
|
||||||
|
|
||||||
/// Basis class to compute tangent space basis, ortogonalizations and to
|
/// Basis class to compute tangent space basis, ortogonalizations and to
|
||||||
/// transform vectors from one space to another.
|
/// transform vectors from one space to another.
|
||||||
struct Basis
|
class Basis
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
/// Create a null basis.
|
/// Create a null basis.
|
||||||
Basis() : tangent(0, 0, 0), bitangent(0, 0, 0), normal(0, 0, 0) {}
|
Basis() : tangent(0, 0, 0), bitangent(0, 0, 0), normal(0, 0, 0) {}
|
||||||
|
|
||||||
|
|
97
src/nvmath/Bezier.cpp
Normal file
97
src/nvmath/Bezier.cpp
Normal file
|
@ -0,0 +1,97 @@
|
||||||
|
// This code is in the public domain -- castanyo@yahoo.es
|
||||||
|
|
||||||
|
#include "Bezier.h"
|
||||||
|
|
||||||
|
|
||||||
|
using namespace nv;
|
||||||
|
|
||||||
|
|
||||||
|
static void deCasteljau(float u, Vector3::Arg p0, Vector3::Arg p1, Vector3::Arg p2, Vector3::Arg p3, Vector3 * p)
|
||||||
|
{
|
||||||
|
Vector3 q0 = lerp(p0, p1, u);
|
||||||
|
Vector3 q1 = lerp(p1, p2, u);
|
||||||
|
Vector3 q2 = lerp(p2, p3, u);
|
||||||
|
Vector3 r0 = lerp(q0, q1, u);
|
||||||
|
Vector3 r1 = lerp(q1, q2, u);
|
||||||
|
|
||||||
|
*p = lerp(r0, r1, u);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void deCasteljau(float u, Vector3::Arg p0, Vector3::Arg p1, Vector3::Arg p2, Vector3::Arg p3, Vector3 * p, Vector3 * dp)
|
||||||
|
{
|
||||||
|
Vector3 q0 = lerp(p0, p1, u);
|
||||||
|
Vector3 q1 = lerp(p1, p2, u);
|
||||||
|
Vector3 q2 = lerp(p2, p3, u);
|
||||||
|
Vector3 r0 = lerp(q0, q1, u);
|
||||||
|
Vector3 r1 = lerp(q1, q2, u);
|
||||||
|
|
||||||
|
*dp = r0 - r1;
|
||||||
|
*p = lerp(r0, r1, u);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void nv::evaluateCubicBezierPatch(float u, float v,
|
||||||
|
Vector3::Arg p0, Vector3::Arg p1, Vector3::Arg p2, Vector3::Arg p3,
|
||||||
|
Vector3::Arg p4, Vector3::Arg p5, Vector3::Arg p6, Vector3::Arg p7,
|
||||||
|
Vector3::Arg p8, Vector3::Arg p9, Vector3::Arg pA, Vector3::Arg pB,
|
||||||
|
Vector3::Arg pC, Vector3::Arg pD, Vector3::Arg pE, Vector3::Arg pF,
|
||||||
|
Vector3 * pos, Vector3 * du, Vector3 * dv)
|
||||||
|
{
|
||||||
|
#if 0
|
||||||
|
Vector2 L0(1-u,1-v);
|
||||||
|
Vector2 L1(u,v);
|
||||||
|
|
||||||
|
Vector2 Q0 = L0 * L0;
|
||||||
|
Vector2 Q1 = 2 * L0 * L1;
|
||||||
|
Vector2 Q2 = L1 * L1;
|
||||||
|
|
||||||
|
Vector2 B0 = L0 * L0 * L0;
|
||||||
|
Vector2 B1 = 3 * L0 * L0 * L1;
|
||||||
|
Vector2 B2 = 3 * L1 * L1 * L0;
|
||||||
|
Vector2 B3 = L1 * L1 * L1;
|
||||||
|
|
||||||
|
*pos =
|
||||||
|
(B0.x() * p0 + B1.x() * p1 + B2.x() * p2 + B3.x() * p3) * B0.y() +
|
||||||
|
(B0.x() * p4 + B1.x() * p5 + B2.x() * p6 + B3.x() * p7) * B1.y() +
|
||||||
|
(B0.x() * p8 + B1.x() * p9 + B2.x() * pA + B3.x() * pB) * B2.y() +
|
||||||
|
(B0.x() * pC + B1.x() * pD + B2.x() * pE + B3.x() * pF) * B3.y();
|
||||||
|
|
||||||
|
*du =
|
||||||
|
((p0-p1) * B0.y() + (p4-p5) * B1.y() + (p8-p9) * B2.y() + (pC-pD) * B3.y()) * Q0.x() +
|
||||||
|
((p1-p2) * B0.y() + (p5-p6) * B1.y() + (p9-pA) * B2.y() + (pD-pE) * B3.y()) * Q1.x() +
|
||||||
|
((p2-p3) * B0.y() + (p6-p7) * B1.y() + (pA-pB) * B2.y() + (pE-pF) * B3.y()) * Q2.x();
|
||||||
|
|
||||||
|
*dv =
|
||||||
|
((p0-p4) * B0.x() + (p1-p5) * B1.x() + (p2-p6) * B2.x() + (p3-p7) * B3.x()) * Q0.y() +
|
||||||
|
((p4-p8) * B0.x() + (p5-p9) * B1.x() + (p6-pA) * B2.x() + (p7-pB) * B3.x()) * Q1.y() +
|
||||||
|
((p8-pC) * B0.x() + (p9-pD) * B1.x() + (pA-pE) * B2.x() + (pB-pF) * B3.x()) * Q2.y();
|
||||||
|
#else
|
||||||
|
Vector3 t0, t1, t2, t3;
|
||||||
|
Vector3 q0, q1, q2, q3;
|
||||||
|
|
||||||
|
deCasteljau(u, p0, p1, p2, p3, &q0, &t0);
|
||||||
|
deCasteljau(u, p4, p5, p6, p7, &q1, &t1);
|
||||||
|
deCasteljau(u, p8, p9, pA, pB, &q2, &t2);
|
||||||
|
deCasteljau(u, pC, pD, pE, pF, &q3, &t3);
|
||||||
|
|
||||||
|
deCasteljau(v, q0, q1, q2, q3, pos, dv);
|
||||||
|
deCasteljau(v, t0, t1, t2, t3, du);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void nv::degreeElevate(Vector3::Arg p0, Vector3::Arg p1, Vector3::Arg p2, Vector3::Arg p3,
|
||||||
|
Vector3 * q0, Vector3 * q1, Vector3 * q2, Vector3 * q3, Vector3 * q4)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void nv::evaluateQuarticBezierTriangle(float u, float v,
|
||||||
|
Vector3::Arg p0, Vector3::Arg p1, Vector3::Arg p2, Vector3::Arg p3, Vector3::Arg p4,
|
||||||
|
Vector3::Arg p5, Vector3::Arg p6, Vector3::Arg p7, Vector3::Arg p8,
|
||||||
|
Vector3::Arg p9, Vector3::Arg pA, Vector3::Arg pB,
|
||||||
|
Vector3::Arg pC, Vector3::Arg pD,
|
||||||
|
Vector3::Arg pE,
|
||||||
|
Vector3 * pos, Vector3 * du, Vector3 * dv)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
33
src/nvmath/Bezier.h
Normal file
33
src/nvmath/Bezier.h
Normal file
|
@ -0,0 +1,33 @@
|
||||||
|
// This code is in the public domain -- castanyo@yahoo.es
|
||||||
|
|
||||||
|
#ifndef NV_MATH_BEZIER_H
|
||||||
|
#define NV_MATH_BEZIER_H
|
||||||
|
|
||||||
|
#include <nvmath/nvmath.h>
|
||||||
|
#include <nvmath/Vector.h>
|
||||||
|
|
||||||
|
namespace nv
|
||||||
|
{
|
||||||
|
|
||||||
|
void evaluateCubicBezierPatch(float u, float v,
|
||||||
|
Vector3::Arg p0, Vector3::Arg p1, Vector3::Arg p2, Vector3::Arg p3,
|
||||||
|
Vector3::Arg p4, Vector3::Arg p5, Vector3::Arg p6, Vector3::Arg p7,
|
||||||
|
Vector3::Arg p8, Vector3::Arg p9, Vector3::Arg pA, Vector3::Arg pB,
|
||||||
|
Vector3::Arg pC, Vector3::Arg pD, Vector3::Arg pE, Vector3::Arg pF,
|
||||||
|
Vector3 * pos, Vector3 * du, Vector3 * dv);
|
||||||
|
|
||||||
|
void degreeElevate(Vector3::Arg p0, Vector3::Arg p1, Vector3::Arg p2, Vector3::Arg p3,
|
||||||
|
Vector3 * q0, Vector3 * q1, Vector3 * q2, Vector3 * q3, Vector3 * q4);
|
||||||
|
|
||||||
|
void evaluateQuarticBezierTriangle(float u, float v,
|
||||||
|
Vector3::Arg p0, Vector3::Arg p1, Vector3::Arg p2, Vector3::Arg p3, Vector3::Arg p4,
|
||||||
|
Vector3::Arg p5, Vector3::Arg p6, Vector3::Arg p7, Vector3::Arg p8,
|
||||||
|
Vector3::Arg p9, Vector3::Arg pA, Vector3::Arg pB,
|
||||||
|
Vector3::Arg pC, Vector3::Arg pD,
|
||||||
|
Vector3::Arg pE,
|
||||||
|
Vector3 * pos, Vector3 * du, Vector3 * dv);
|
||||||
|
|
||||||
|
|
||||||
|
} // nv namespace
|
||||||
|
|
||||||
|
#endif // NV_MATH_BEZIER_H
|
|
@ -8,6 +8,7 @@ SET(MATH_SRCS
|
||||||
Plane.h Plane.cpp
|
Plane.h Plane.cpp
|
||||||
Box.h
|
Box.h
|
||||||
Color.h
|
Color.h
|
||||||
|
Frustum.h Frustum.cpp
|
||||||
Montecarlo.h Montecarlo.cpp
|
Montecarlo.h Montecarlo.cpp
|
||||||
Random.h Random.cpp
|
Random.h Random.cpp
|
||||||
SphericalHarmonic.h SphericalHarmonic.cpp
|
SphericalHarmonic.h SphericalHarmonic.cpp
|
||||||
|
@ -19,7 +20,8 @@ SET(MATH_SRCS
|
||||||
Solver.h Solver.cpp
|
Solver.h Solver.cpp
|
||||||
KahanSum.h
|
KahanSum.h
|
||||||
Half.h Half.cpp
|
Half.h Half.cpp
|
||||||
Fitting.h Fitting.cpp)
|
Fitting.h Fitting.cpp
|
||||||
|
Bezier.h Bezier.cpp)
|
||||||
|
|
||||||
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
INCLUDE_DIRECTORIES(${CMAKE_CURRENT_SOURCE_DIR})
|
||||||
|
|
||||||
|
|
76
src/nvmath/Frustum.cpp
Normal file
76
src/nvmath/Frustum.cpp
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
// This code is in the public domain -- castanyo@yahoo.es
|
||||||
|
|
||||||
|
#include "Frustum.h"
|
||||||
|
#include "Box.h"
|
||||||
|
#include "Matrix.h"
|
||||||
|
|
||||||
|
namespace nv
|
||||||
|
{
|
||||||
|
Frustum::Frustum(float fovy, float aspect, float near, float far)
|
||||||
|
{
|
||||||
|
// Define a frustum looking along the -ve z axis.
|
||||||
|
planes[NEAR] = Plane(Vector3(0,0,1), near);
|
||||||
|
planes[FAR] = Plane(Vector3(0,0,-1), far);
|
||||||
|
|
||||||
|
const Vector3 origin(zero);
|
||||||
|
const float tanfy = tan(fovy/2.0f);
|
||||||
|
planes[TOP] = Plane(Vector3( 1.0f, 0.0f, tanfy * aspect), origin);
|
||||||
|
planes[BOTTOM] = Plane(Vector3(-1.0f, 0.0f, tanfy * aspect), origin);
|
||||||
|
|
||||||
|
planes[RIGHT] = Plane(Vector3(0.0f, 1.0f, tanfy), origin);
|
||||||
|
planes[LEFT] = Plane(Vector3(0.0f, -1.0f, tanfy), origin);
|
||||||
|
|
||||||
|
for(int p = 0; p < Frustum::PLANE_COUNT; ++p)
|
||||||
|
planes[p] = normalize(planes[p]);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void getAllCorners(const Box& boxy, Vector3 c[])
|
||||||
|
{
|
||||||
|
c[0] = boxy.minCorner();
|
||||||
|
c[1] = boxy.maxCorner();
|
||||||
|
c[2] = Vector3(c[0].x(), c[1].y(), c[0].z());
|
||||||
|
c[3] = Vector3(c[0].x(), c[1].y(), c[1].z());
|
||||||
|
c[4] = Vector3(c[0].x(), c[0].y(), c[1].z());
|
||||||
|
c[5] = Vector3(c[1].x(), c[1].y(), c[0].z());
|
||||||
|
c[6] = Vector3(c[1].x(), c[0].y(), c[0].z());
|
||||||
|
c[7] = Vector3(c[1].x(), c[0].y(), c[1].z());
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Frustum::intersects(const Box& boxy) const
|
||||||
|
{
|
||||||
|
const int N_CORNERS = 8;
|
||||||
|
Vector3 boxCorners[N_CORNERS];
|
||||||
|
getAllCorners(boxy, boxCorners);
|
||||||
|
|
||||||
|
// test all 8 corners against the 6 sides
|
||||||
|
// if all points are behind 1 specific plane, we are out
|
||||||
|
// if we are in with all points, then we are fully in
|
||||||
|
for(int p = 0; p < Frustum::PLANE_COUNT; ++p)
|
||||||
|
{
|
||||||
|
int iInCount = N_CORNERS;
|
||||||
|
|
||||||
|
for(int i = 0; i < N_CORNERS; ++i)
|
||||||
|
{
|
||||||
|
// test point [i] against the planes
|
||||||
|
if (distance(planes[p], boxCorners[i]) > 0.0f)
|
||||||
|
--iInCount;
|
||||||
|
}
|
||||||
|
|
||||||
|
// were all the points outside of plane p?
|
||||||
|
if (iInCount == 0)
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
Frustum transformFrustum(const Matrix& m, const Frustum& f)
|
||||||
|
{
|
||||||
|
Frustum result;
|
||||||
|
|
||||||
|
for (int i=0; i!=Frustum::PLANE_COUNT; ++i)
|
||||||
|
result.planes[i] = transformPlane(m, f.planes[i]);
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
34
src/nvmath/Frustum.h
Normal file
34
src/nvmath/Frustum.h
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
// This code is in the public domain -- castanyo@yahoo.es
|
||||||
|
|
||||||
|
#ifndef NV_MATH_FRUSTUM_H
|
||||||
|
#define NV_MATH_FRUSTUM_H
|
||||||
|
|
||||||
|
#include <nvmath/Plane.h>
|
||||||
|
|
||||||
|
namespace nv
|
||||||
|
{
|
||||||
|
class Box;
|
||||||
|
|
||||||
|
class NVMATH_CLASS Frustum
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
// Construct a frustum from typical view parameters. fovy has the same meaning as for glut_perspective_reshaper.
|
||||||
|
// The resulting frustum is centred at the origin, pointing along the z-axis.
|
||||||
|
Frustum() {}
|
||||||
|
Frustum(float fovy, float aspect, float near, float far);
|
||||||
|
|
||||||
|
// Unlike some intersection methods, we don't bother to distinguish intersects
|
||||||
|
// from contains. A true result could indicate either.
|
||||||
|
bool intersects(const Box&) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
friend Frustum transformFrustum(const Matrix&, const Frustum&);
|
||||||
|
|
||||||
|
enum PlaneIndices { NEAR, LEFT, RIGHT, TOP, BOTTOM, FAR, PLANE_COUNT };
|
||||||
|
Plane planes[PLANE_COUNT];
|
||||||
|
};
|
||||||
|
|
||||||
|
Frustum transformFrustum(const Matrix&, const Frustum&);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -24,6 +24,8 @@ public:
|
||||||
Matrix(zero_t);
|
Matrix(zero_t);
|
||||||
Matrix(identity_t);
|
Matrix(identity_t);
|
||||||
Matrix(const Matrix & m);
|
Matrix(const Matrix & m);
|
||||||
|
Matrix(Vector4::Arg v0, Vector4::Arg v1, Vector4::Arg v2, Vector4::Arg v3);
|
||||||
|
Matrix(const scalar m[]); // m is assumed to contain 16 elements
|
||||||
|
|
||||||
scalar data(uint idx) const;
|
scalar data(uint idx) const;
|
||||||
scalar & data(uint idx);
|
scalar & data(uint idx);
|
||||||
|
@ -75,6 +77,21 @@ inline Matrix::Matrix(const Matrix & m)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline Matrix::Matrix(Vector4::Arg v0, Vector4::Arg v1, Vector4::Arg v2, Vector4::Arg v3)
|
||||||
|
{
|
||||||
|
m_data[ 0] = v0.x(); m_data[ 1] = v0.y(); m_data[ 2] = v0.z(); m_data[ 3] = v0.w();
|
||||||
|
m_data[ 4] = v1.x(); m_data[ 5] = v1.y(); m_data[ 6] = v1.z(); m_data[ 7] = v1.w();
|
||||||
|
m_data[ 8] = v2.x(); m_data[ 9] = v2.y(); m_data[10] = v2.z(); m_data[11] = v2.w();
|
||||||
|
m_data[12] = v3.x(); m_data[13] = v3.y(); m_data[14] = v3.z(); m_data[15] = v3.w();
|
||||||
|
}
|
||||||
|
|
||||||
|
inline Matrix::Matrix(const scalar m[])
|
||||||
|
{
|
||||||
|
for(int i = 0; i < 16; i++) {
|
||||||
|
m_data[i] = m[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// Accessors
|
// Accessors
|
||||||
inline scalar Matrix::data(uint idx) const
|
inline scalar Matrix::data(uint idx) const
|
||||||
|
@ -332,7 +349,7 @@ inline Matrix transpose(Matrix::Arg m)
|
||||||
Matrix r;
|
Matrix r;
|
||||||
for (int i = 0; i < 4; i++)
|
for (int i = 0; i < 4; i++)
|
||||||
{
|
{
|
||||||
for (int j = 0; j < 4; i++)
|
for (int j = 0; j < 4; j++)
|
||||||
{
|
{
|
||||||
r(i, j) = m(j, i);
|
r(i, j) = m(j, i);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,14 +31,7 @@ void SampleDistribution::redistributeRandom(const Distribution dist)
|
||||||
float x = m_rand.getFloat();
|
float x = m_rand.getFloat();
|
||||||
float y = m_rand.getFloat();
|
float y = m_rand.getFloat();
|
||||||
|
|
||||||
// Map uniform distribution in the square to the (hemi)sphere.
|
setSample(i, dist, x, y);
|
||||||
if( dist == Distribution_Uniform ) {
|
|
||||||
m_sampleArray[i].setUV(acosf(1 - 2 * x), 2 * PI * y);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
nvDebugCheck(dist == Distribution_Cosine);
|
|
||||||
m_sampleArray[i].setUV(acosf(sqrtf(x)), 2 * PI * y);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,14 +49,7 @@ void SampleDistribution::redistributeStratified(const Distribution dist)
|
||||||
float x = (u + m_rand.getFloat()) / float(sqrtSampleCount);
|
float x = (u + m_rand.getFloat()) / float(sqrtSampleCount);
|
||||||
float y = (v + m_rand.getFloat()) / float(sqrtSampleCount);
|
float y = (v + m_rand.getFloat()) / float(sqrtSampleCount);
|
||||||
|
|
||||||
// Map uniform distribution in the square to the (hemi)sphere.
|
setSample(i, dist, x, y);
|
||||||
if( dist == Distribution_Uniform ) {
|
|
||||||
m_sampleArray[i].setUV(acosf(1 - 2 * x), 2 * PI * y);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
nvDebugCheck(dist == Distribution_Cosine);
|
|
||||||
m_sampleArray[i].setUV(acosf(sqrtf(x)), 2 * PI * y);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -141,14 +127,7 @@ void SampleDistribution::redistributeNRook(const Distribution dist)
|
||||||
float x = (i + m_rand.getFloat()) / sampleCount;
|
float x = (i + m_rand.getFloat()) / sampleCount;
|
||||||
float y = (cells[i] + m_rand.getFloat()) / sampleCount;
|
float y = (cells[i] + m_rand.getFloat()) / sampleCount;
|
||||||
|
|
||||||
// Map uniform distribution in the square to the (hemi)sphere.
|
setSample(i, dist, x, y);
|
||||||
if( dist == Distribution_Uniform ) {
|
|
||||||
m_sampleArray[i].setUV(acosf(1 - 2 * x), 2 * PI * y);
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
nvDebugCheck(dist == Distribution_Cosine);
|
|
||||||
m_sampleArray[i].setUV(acosf(sqrtf(x)), 2 * PI * y);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
delete [] cells;
|
delete [] cells;
|
||||||
|
|
|
@ -23,23 +23,26 @@ public:
|
||||||
|
|
||||||
// Distribution functions.
|
// Distribution functions.
|
||||||
enum Distribution {
|
enum Distribution {
|
||||||
Distribution_Uniform,
|
Distribution_UniformSphere,
|
||||||
Distribution_Cosine
|
Distribution_UniformHemisphere,
|
||||||
|
Distribution_CosineHemisphere
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Constructor.
|
/// Constructor.
|
||||||
SampleDistribution(int num)
|
SampleDistribution(uint num)
|
||||||
{
|
{
|
||||||
m_sampleArray.resize(num);
|
m_sampleArray.resize(num);
|
||||||
}
|
}
|
||||||
|
|
||||||
void redistribute(Method method=Method_NRook, Distribution dist=Distribution_Cosine);
|
uint count() const { return m_sampleArray.count(); }
|
||||||
|
|
||||||
|
void redistribute(Method method=Method_NRook, Distribution dist=Distribution_CosineHemisphere);
|
||||||
|
|
||||||
/// Get parametric coordinates of the sample.
|
/// Get parametric coordinates of the sample.
|
||||||
Vector2 sample(int i) { return m_sampleArray[i].uv; }
|
Vector2 sample(int i) const { return m_sampleArray[i].uv; }
|
||||||
|
|
||||||
/// Get sample direction.
|
/// Get sample direction.
|
||||||
Vector3 sampleDir(int i) { return m_sampleArray[i].dir; }
|
Vector3 sampleDir(int i) const { return m_sampleArray[i].dir; }
|
||||||
|
|
||||||
/// Get number of samples.
|
/// Get number of samples.
|
||||||
uint sampleCount() const { return m_sampleArray.count(); }
|
uint sampleCount() const { return m_sampleArray.count(); }
|
||||||
|
@ -71,6 +74,22 @@ private:
|
||||||
Vector3 dir;
|
Vector3 dir;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
inline void setSample(uint i, Distribution dist, float x, float y)
|
||||||
|
{
|
||||||
|
// Map uniform distribution in the square to desired domain.
|
||||||
|
if( dist == Distribution_UniformSphere ) {
|
||||||
|
m_sampleArray[i].setUV(acosf(1 - 2 * x), 2 * PI * y);
|
||||||
|
}
|
||||||
|
else if( dist == Distribution_UniformHemisphere ) {
|
||||||
|
m_sampleArray[i].setUV(acosf(x), 2 * PI * y);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
nvDebugCheck(dist == Distribution_CosineHemisphere);
|
||||||
|
m_sampleArray[i].setUV(acosf(sqrtf(x)), 2 * PI * y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Random seed.
|
/// Random seed.
|
||||||
MTRand m_rand;
|
MTRand m_rand;
|
||||||
|
|
||||||
|
|
|
@ -44,7 +44,15 @@ namespace
|
||||||
|
|
||||||
void apply(const FullVector & x, FullVector & y) const
|
void apply(const FullVector & x, FullVector & y) const
|
||||||
{
|
{
|
||||||
y *= x;
|
nvDebugCheck(x.dimension() == m_inverseDiagonal.dimension());
|
||||||
|
nvDebugCheck(y.dimension() == m_inverseDiagonal.dimension());
|
||||||
|
|
||||||
|
// @@ Wrap vector component-wise product into a separate function.
|
||||||
|
const uint D = x.dimension();
|
||||||
|
for (uint i = 0; i < D; i++)
|
||||||
|
{
|
||||||
|
y[i] = m_inverseDiagonal[i] * x[i];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
@ -69,11 +77,16 @@ void nv::LeastSquaresSolver(const SparseMatrix & A, const FullVector & b, FullVe
|
||||||
|
|
||||||
const uint D = A.width();
|
const uint D = A.width();
|
||||||
|
|
||||||
|
SparseMatrix At(A.height(), A.width());
|
||||||
|
transpose(A, At);
|
||||||
|
|
||||||
FullVector Atb(D);
|
FullVector Atb(D);
|
||||||
mult(Transposed, A, b, Atb);
|
//mult(Transposed, A, b, Atb);
|
||||||
|
mult(At, b, Atb);
|
||||||
|
|
||||||
SparseMatrix AtA(D);
|
SparseMatrix AtA(D);
|
||||||
mult(Transposed, A, NoTransposed, A, AtA);
|
//mult(Transposed, A, NoTransposed, A, AtA);
|
||||||
|
mult(At, A, AtA);
|
||||||
|
|
||||||
SymmetricSolver(AtA, Atb, x, epsilon);
|
SymmetricSolver(AtA, Atb, x, epsilon);
|
||||||
}
|
}
|
||||||
|
@ -182,10 +195,10 @@ void nv::SymmetricSolver(const SparseMatrix & A, const FullVector & b, FullVecto
|
||||||
nvDebugCheck(A.height() == b.dimension());
|
nvDebugCheck(A.height() == b.dimension());
|
||||||
nvDebugCheck(b.dimension() == x.dimension());
|
nvDebugCheck(b.dimension() == x.dimension());
|
||||||
|
|
||||||
// JacobiPreconditioner jacobi(A, true);
|
JacobiPreconditioner jacobi(A, true);
|
||||||
|
ConjugateGradientSolver(jacobi, A, b, x, epsilon);
|
||||||
|
|
||||||
// ConjugateGradientSolver(jacobi, A, b, x, epsilon);
|
// ConjugateGradientSolver(A, b, x, epsilon);
|
||||||
ConjugateGradientSolver(A, b, x, epsilon);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -280,9 +293,9 @@ void nv::SymmetricSolver(const SparseMatrix & A, const FullVector & b, FullVecto
|
||||||
|
|
||||||
beta = delta_new / delta_old;
|
beta = delta_new / delta_old;
|
||||||
|
|
||||||
// p = r + beta·p
|
// p = beta·p + r
|
||||||
copy(r, p);
|
scal(beta, p);
|
||||||
saxpy(beta, p, r);
|
saxpy(1, r, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
|
@ -358,8 +371,8 @@ void nv::SymmetricSolver(const SparseMatrix & A, const FullVector & b, FullVecto
|
||||||
beta = delta_new / delta_old;
|
beta = delta_new / delta_old;
|
||||||
|
|
||||||
// p = s + beta·p
|
// p = s + beta·p
|
||||||
copy(s, p);
|
scal(beta, p);
|
||||||
saxpy(beta, p, s);
|
saxpy(1, s, p);
|
||||||
}
|
}
|
||||||
|
|
||||||
return i;
|
return i;
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// This code is in the public domain -- Ignacio Castao <castanyo@yahoo.es>
|
// This code is in the public domain -- Ignacio Castaño <castanyo@yahoo.es>
|
||||||
|
|
||||||
#include <nvmath/Sparse.h>
|
#include <nvmath/Sparse.h>
|
||||||
#include <nvmath/KahanSum.h>
|
#include <nvmath/KahanSum.h>
|
||||||
|
@ -235,7 +235,7 @@ void FullMatrix::madRow(uint y, float alpha, FullVector & v) const
|
||||||
const uint count = v.dimension();
|
const uint count = v.dimension();
|
||||||
for (uint i = 0; i < count; i++)
|
for (uint i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
v[i] += alpha * m_array[y * count + i];
|
v[i] += m_array[y * count + i];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -432,8 +432,11 @@ void SparseMatrix::setCoefficient(uint x, uint y, float f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Coefficient c = { x, f };
|
if (f != 0.0f)
|
||||||
m_array[y].append( c );
|
{
|
||||||
|
Coefficient c = { x, f };
|
||||||
|
m_array[y].append( c );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SparseMatrix::addCoefficient(uint x, uint y, float f)
|
void SparseMatrix::addCoefficient(uint x, uint y, float f)
|
||||||
|
@ -441,18 +444,21 @@ void SparseMatrix::addCoefficient(uint x, uint y, float f)
|
||||||
nvDebugCheck( x < width() );
|
nvDebugCheck( x < width() );
|
||||||
nvDebugCheck( y < height() );
|
nvDebugCheck( y < height() );
|
||||||
|
|
||||||
const uint count = m_array[y].count();
|
if (f != 0.0f)
|
||||||
for (uint i = 0; i < count; i++)
|
|
||||||
{
|
{
|
||||||
if (m_array[y][i].x == x)
|
const uint count = m_array[y].count();
|
||||||
|
for (uint i = 0; i < count; i++)
|
||||||
{
|
{
|
||||||
m_array[y][i].v += f;
|
if (m_array[y][i].x == x)
|
||||||
return;
|
{
|
||||||
|
m_array[y][i].v += f;
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
Coefficient c = { x, f };
|
Coefficient c = { x, f };
|
||||||
m_array[y].append( c );
|
m_array[y].append( c );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SparseMatrix::mulCoefficient(uint x, uint y, float f)
|
void SparseMatrix::mulCoefficient(uint x, uint y, float f)
|
||||||
|
@ -470,8 +476,11 @@ void SparseMatrix::mulCoefficient(uint x, uint y, float f)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Coefficient c = { x, f };
|
if (f != 0.0f)
|
||||||
m_array[y].append( c );
|
{
|
||||||
|
Coefficient c = { x, f };
|
||||||
|
m_array[y].append( c );
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -753,6 +762,32 @@ static float dotColumnColumn(int y, const SparseMatrix & A, int x, const SparseM
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void nv::transpose(const SparseMatrix & A, SparseMatrix & B)
|
||||||
|
{
|
||||||
|
nvDebugCheck(A.width() == B.height());
|
||||||
|
nvDebugCheck(B.width() == A.height());
|
||||||
|
|
||||||
|
const uint w = A.width();
|
||||||
|
for (uint x = 0; x < w; x++)
|
||||||
|
{
|
||||||
|
B.clearRow(x);
|
||||||
|
}
|
||||||
|
|
||||||
|
const uint h = A.height();
|
||||||
|
for (uint y = 0; y < h; y++)
|
||||||
|
{
|
||||||
|
const Array<SparseMatrix::Coefficient> & row = A.getRow(y);
|
||||||
|
|
||||||
|
const uint count = row.count();
|
||||||
|
for (uint i = 0; i < count; i++)
|
||||||
|
{
|
||||||
|
const SparseMatrix::Coefficient & c = row[i];
|
||||||
|
nvDebugCheck(c.x < w);
|
||||||
|
|
||||||
|
B.setCoefficient(y, c.x, c.v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// C = A * B
|
// C = A * B
|
||||||
void nv::mult(const SparseMatrix & A, const SparseMatrix & B, SparseMatrix & C)
|
void nv::mult(const SparseMatrix & A, const SparseMatrix & B, SparseMatrix & C)
|
||||||
|
@ -814,13 +849,9 @@ void nv::sgemm(float alpha, Transpose TA, const SparseMatrix & A, Transpose TB,
|
||||||
c += alpha * dotRowRow(y, A, x, B);
|
c += alpha * dotRowRow(y, A, x, B);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (c != 0.0f)
|
C.setCoefficient(x, y, c);
|
||||||
{
|
|
||||||
C.setCoefficient(x, y, c);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// C = At * A
|
// C = At * A
|
||||||
|
|
|
@ -175,6 +175,8 @@ namespace nv
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
NVMATH_API void transpose(const SparseMatrix & A, SparseMatrix & B);
|
||||||
|
|
||||||
NVMATH_API void mult(const SparseMatrix & M, const FullVector & x, FullVector & y);
|
NVMATH_API void mult(const SparseMatrix & M, const FullVector & x, FullVector & y);
|
||||||
NVMATH_API void mult(Transpose TM, const SparseMatrix & M, const FullVector & x, FullVector & y);
|
NVMATH_API void mult(Transpose TM, const SparseMatrix & M, const FullVector & x, FullVector & y);
|
||||||
|
|
||||||
|
|
|
@ -7,6 +7,7 @@
|
||||||
#include <nvmath/Quaternion.h>
|
#include <nvmath/Quaternion.h>
|
||||||
#include <nvmath/Basis.h>
|
#include <nvmath/Basis.h>
|
||||||
#include <nvmath/Box.h>
|
#include <nvmath/Box.h>
|
||||||
|
#include <nvmath/Plane.h>
|
||||||
|
|
||||||
#include <nvmath/TypeSerialization.h>
|
#include <nvmath/TypeSerialization.h>
|
||||||
|
|
||||||
|
@ -80,3 +81,7 @@ Stream & nv::operator<< (Stream & s, Box & box)
|
||||||
return s << box.m_mins << box.m_maxs;
|
return s << box.m_mins << box.m_maxs;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Stream & nv::operator<< (Stream & s, Plane & plane)
|
||||||
|
{
|
||||||
|
return s << plane.asVector();
|
||||||
|
}
|
||||||
|
|
|
@ -15,8 +15,9 @@ namespace nv
|
||||||
|
|
||||||
class Matrix;
|
class Matrix;
|
||||||
class Quaternion;
|
class Quaternion;
|
||||||
struct Basis;
|
class Basis;
|
||||||
class Box;
|
class Box;
|
||||||
|
class Plane;
|
||||||
|
|
||||||
NVMATH_API Stream & operator<< (Stream & s, Vector2 & obj);
|
NVMATH_API Stream & operator<< (Stream & s, Vector2 & obj);
|
||||||
NVMATH_API Stream & operator<< (Stream & s, Vector3 & obj);
|
NVMATH_API Stream & operator<< (Stream & s, Vector3 & obj);
|
||||||
|
@ -26,6 +27,7 @@ namespace nv
|
||||||
NVMATH_API Stream & operator<< (Stream & s, Quaternion & obj);
|
NVMATH_API Stream & operator<< (Stream & s, Quaternion & obj);
|
||||||
NVMATH_API Stream & operator<< (Stream & s, Basis & obj);
|
NVMATH_API Stream & operator<< (Stream & s, Basis & obj);
|
||||||
NVMATH_API Stream & operator<< (Stream & s, Box & obj);
|
NVMATH_API Stream & operator<< (Stream & s, Box & obj);
|
||||||
|
NVMATH_API Stream & operator<< (Stream & s, Plane & obj);
|
||||||
|
|
||||||
} // nv namespace
|
} // nv namespace
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ public:
|
||||||
Vector2(Vector2::Arg v);
|
Vector2(Vector2::Arg v);
|
||||||
|
|
||||||
const Vector2 & operator=(Vector2::Arg v);
|
const Vector2 & operator=(Vector2::Arg v);
|
||||||
|
void setComponent(uint idx, scalar f);
|
||||||
|
|
||||||
scalar x() const;
|
scalar x() const;
|
||||||
scalar y() const;
|
scalar y() const;
|
||||||
|
@ -116,6 +117,7 @@ public:
|
||||||
const Vector3 & xyz() const;
|
const Vector3 & xyz() const;
|
||||||
|
|
||||||
scalar component(uint idx) const;
|
scalar component(uint idx) const;
|
||||||
|
void setComponent(uint idx, scalar f);
|
||||||
|
|
||||||
const scalar * ptr() const;
|
const scalar * ptr() const;
|
||||||
|
|
||||||
|
@ -162,6 +164,14 @@ inline scalar Vector2::component(uint idx) const
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void Vector2::setComponent(uint idx, float f)
|
||||||
|
{
|
||||||
|
nvDebugCheck(idx < 2);
|
||||||
|
if (idx == 0) m_x = f;
|
||||||
|
else if (idx == 1) m_y = f;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
inline const scalar * Vector2::ptr() const
|
inline const scalar * Vector2::ptr() const
|
||||||
{
|
{
|
||||||
return &m_x;
|
return &m_x;
|
||||||
|
@ -362,6 +372,15 @@ inline scalar Vector4::component(uint idx) const
|
||||||
return 0.0f;
|
return 0.0f;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void Vector4::setComponent(uint idx, float f)
|
||||||
|
{
|
||||||
|
nvDebugCheck(idx < 4);
|
||||||
|
if (idx == 0) m_x = f;
|
||||||
|
else if (idx == 1) m_y = f;
|
||||||
|
else if (idx == 2) m_z = f;
|
||||||
|
else if (idx == 3) m_w = f;
|
||||||
|
}
|
||||||
|
|
||||||
inline const scalar * Vector4::ptr() const
|
inline const scalar * Vector4::ptr() const
|
||||||
{
|
{
|
||||||
return &m_x;
|
return &m_x;
|
||||||
|
|
Loading…
Reference in New Issue
Block a user