From a955106d187958c2efeced079a3b9b55ceed9e19 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Wed, 6 Aug 2014 21:51:28 -0700 Subject: [PATCH 01/92] Implement a Matrix4 class A 4x4 matrix that implements matrix multiplication and multiplication by scalars. Some unit tests too, to test that this stuff works. --- src/basics.cc | 218 ++++++++++++++++++++++++++++++++++++++++++++ src/basics.h | 75 +++++++++++++++ test/test_basics.cc | 109 ++++++++++++++++++++++ 3 files changed, 402 insertions(+) diff --git a/src/basics.cc b/src/basics.cc index fc4ddd7..7bfe278 100644 --- a/src/basics.cc +++ b/src/basics.cc @@ -9,7 +9,10 @@ * Eryn Wells */ +#include #include +#include + #include "basics.h" #pragma mark - Vectors @@ -271,6 +274,221 @@ LinearCombination(const Double k1, const Vector3& v1, k1 * v1.z + k2 * v2.z + k3 * v3.z); } +#pragma mark - Matrices + +/* static */ Matrix4 +Matrix4::Zero() +{ + Matrix4 m; + memset(m.mCells, 0, 16 * sizeof(Double)); + return m; +} + + +/* static */ Matrix4 +Matrix4::Identity() +{ + Matrix4 m = Zero(); + for (int i = 0; i < 4; i++) { + m.mCells[i * 4 + i] = 1.0; + } + return m; +} + + +/* static */ Matrix4 +Matrix4::Translation(Double x, + Double y, + Double z) +{ + Matrix4 m = Identity(); + m.mCells[3] = x; + m.mCells[7] = y; + m.mCells[11] = z; + return m; +} + + +/* static */ Matrix4 +Matrix4::Rotation(Double x, + Double y, + Double z) +{ + Matrix4 m = Identity(); + + if (x == 0.0 && y == 0.0 && z == 0.0) { + /* No rotation, just return the identity matrix. */ + } else if (x != 0.0 && y == 0.0 && z == 0.0) { + /* + * Fill in m with values for an X rotation matrix. + * + * [1 0 0 0] + * [0 cos(x) -sin(x) 0] + * [0 sin(x) cos(x) 0] + * [0 0 0 1] + */ + Double cosX = std::cos(x); + Double sinX = std::sin(x); + m.mCells[5] = cosX; + m.mCells[6] = -sinX; + m.mCells[9] = sinX; + m.mCells[10] = cosX; + } else if (x == 0.0 && y != 0.0 && z == 0.0) { + /* + * Fill in m with values for a Y rotation matrix. + * + * [ cos(y) 0 sin(y) 0] + * [ 0 1 0 0] + * [-sin(y) 0 cos(y) 0] + * [ 0 0 0 1] + */ + Double cosY = std::cos(y); + Double sinY = std::sin(y); + m.mCells[0] = cosY; + m.mCells[2] = sinY; + m.mCells[8] = -sinY; + m.mCells[10] = cosY; + } else if (x == 0.0 && y == 0.0 && z != 0.0) { + /* + * Fill in m with values for a Z rotation matrix. + * + * [cos(z) -sin(z) 0 0] + * [sin(z) cos(z) 0 0] + * [ 0 0 1 0] + * [ 0 0 0 1] + */ + Double cosZ = std::cos(z); + Double sinZ = std::sin(z); + m.mCells[0] = cosZ; + m.mCells[1] = -sinZ; + m.mCells[4] = sinZ; + m.mCells[5] = cosZ; + } else { + /* + * TODO: Rotation in more than one dimension. So do a general rotation + * matrix. There's some magic way to do this with matrix multiplication + * that avoids gimbal lock. I should figure out how to do it properly. + */ + assert(0); + } + + return m; +} + + +/* + * Matrix4::Matrix4 -- + */ +Matrix4::Matrix4() + : mCells() +{ } + + +/* + * Matrix4::Matrix4 -- + */ +Matrix4::Matrix4(const Double cells[16]) + : mCells() +{ + memcpy(mCells, cells, 16 * sizeof(Double)); +} + + +/* + * Matrix4::Matrix4 -- + */ +Matrix4::Matrix4(const Matrix4& rhs) + : Matrix4(rhs.mCells) +{ } + + +/* + * Matrix4::operator() -- + */ +Double& +Matrix4::operator()(const unsigned int row, + const unsigned int col) +{ + assert(row < 4 && col < 4); + return mCells[4*row + col]; +} + + +/* + * Matrix4::operator* -- + */ +Matrix4 +Matrix4::operator*(const Double rhs) + const +{ + return Matrix4(*this) *= rhs; +} + + +/* + * Matrix4::operator*= -- + */ +Matrix4& +Matrix4::operator*=(const Double rhs) +{ + for (int i = 0; i < 16; i++) { + mCells[i] *= rhs; + } + return *this; +} + + +/* + * Matrix4::operator* -- + */ +Matrix4 +Matrix4::operator*(const Matrix4& rhs) + const +{ + return Matrix4(*this) *= rhs; +} + + +/* + * Matrix4::operator*= + */ +Matrix4& +Matrix4::operator*=(const Matrix4& rhs) +{ + Matrix4 lhs(*this); + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + /* Each cell is Sigma(k=0, 4)(lhs[ik] * rhs[kj]) */ + const int cell = i*4 + j; + mCells[cell] = 0.0; + for (int k = 0; k < 4; k++) { + mCells[cell] += lhs.mCells[i*4 + k] * rhs.mCells[k*4 + j]; + } + } + } + return *this; +} + + +/* + * Matrix4::CArray -- + */ +const Double* +Matrix4::CArray() + const +{ + return mCells; +} + + +Matrix4 +operator*(const Double rhs, + const Matrix4& lhs) +{ + /* Scalar multiplication is commutative. */ + return lhs * rhs; +} + #pragma mark - Rays /* diff --git a/src/basics.h b/src/basics.h index d84c197..d915b60 100644 --- a/src/basics.h +++ b/src/basics.h @@ -119,6 +119,81 @@ Vector3 LinearCombination(const Double k1, const Vector3& v1, const Double k3, const Vector3& v3); +struct Matrix4 +{ + /** Create a 4x4 zero matrix. That is, all cells are 0. */ + static Matrix4 Zero(); + + /** Create a 4x4 identity matrix. */ + static Matrix4 Identity(); + + Matrix4(); + Matrix4(const Double cells[16]); + Matrix4(const Matrix4& rhs); + + /** + * Create a 4x4 translation matrix. A translation matrix looks like this: + * + * [1 0 0 x] + * [0 1 0 y] + * [0 0 1 z] + * [0 0 0 1] + * + * @param [in] x X translation + * @param [in] y Y translation + * @param [in] z Z translation + * @returns The translation matrix + */ + static Matrix4 Translation(Double x, Double y, Double z); + + /** + * Create a 4x4 rotation matrix. A rotation matrices are quite complicated. + * + * @param [in] x X rotation angle in radians + * @param [in] y Y rotation angle in radians + * @param [in] z Z rotation angle in radians + * @returns The rotation matrix + */ + static Matrix4 Rotation(Double x, Double y, Double z); + + /** + * Get the value of the cell at (row, col). + * + * @param [in] row The row, must be less than the matrix's width + * @param [in] col The column, must be less than the matrix's height + * @returns The value of the cell at (row, col) + */ + Double& operator()(const unsigned int row, const unsigned int col); + + /** + * Scalar multiplication. + * + * @param [in] rhs The scalar factor + * @returns A copy of this matrix, multiplied by the scalar + */ + Matrix4 operator*(const Double rhs) const; + + /** + * Scalar multiplication. Multiplies this matrix by the given factor. + * + * @param [in] rhs The scalar factor + * @returns *this + */ + Matrix4& operator*=(const Double rhs); + + Matrix4 operator*(const Matrix4& rhs) const; + Matrix4& operator*=(const Matrix4& rhs); + + const Double* CArray() const; + +private: + Double mCells[16]; +}; + + +Matrix4 operator*(const Double lhs, const Matrix4& rhs); + + struct Ray { Ray(); diff --git a/test/test_basics.cc b/test/test_basics.cc index a6395b1..374a668 100644 --- a/test/test_basics.cc +++ b/test/test_basics.cc @@ -162,3 +162,112 @@ TEST_F(Vector3Test, DotProduct) { EXPECT_EQ(131.0, v1.dot(v2)); } + +#pragma mark Matrix4 Tests + +class Matrix4Test + : public ::testing::Test +{ +public: + virtual void SetUp(); + +protected: + Matrix4 m1, m2; +}; + + +void +Matrix4Test::SetUp() +{ + const Double m1Cells[] = { 1, 2, 3, 4, + 5, 6, 7, 8, + 9, 10, 11, 12, + 13, 14, 15, 16}; + m1 = Matrix4(m1Cells); + + const Double m2Cells[] = { 1, 1, 2, 3, + 5, 8, 13, 21, + 34, 55, 89, 144, + 233, 377, 610, 987}; + m2 = Matrix4(m2Cells); +} + + +TEST(Matrix4StaticTest, Zero) +{ + Matrix4 zero = Matrix4::Zero(); + for (int i = 0; i < 16; i++) { + EXPECT_EQ(zero.CArray()[i], 0.0); + } +} + + +TEST(Matrix4StaticTest, Identity) +{ + Matrix4 id = Matrix4::Identity(); + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + EXPECT_EQ(id.CArray()[i * 4 + j], ((i == j) ? 1.0 : 0.0)); + } + } +} + + +TEST_F(Matrix4Test, OperatorCall) +{ + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + EXPECT_EQ(m1(i, j), 4 * i + j + 1); + } + } +} + + +TEST_F(Matrix4Test, ScalarMultiplication) +{ + Matrix4 p1 = m1 * 2.0; + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + EXPECT_EQ(p1(i, j), m1(i, j) * 2.0); + } + } + + Matrix4 p2 = 2.0 * m1; + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + EXPECT_EQ(p2(i, j), m1(i, j) * 2.0); + } + } +} + + +TEST_F(Matrix4Test, MatrixMultiplication) +{ + const Double p1Expect[] = {1045, 1690, 2735, 4425, + 2137, 3454, 5591, 9045, + 3229, 5218, 8447, 13665, + 4321, 6982, 11303, 18285}; + Matrix4 p1 = m1 * m2; + for (int i = 0; i < 16; i++) { + EXPECT_EQ(p1.CArray()[i], p1Expect[i]); + } + + const Double p2Expect[] = { 63, 70, 77, 84, + 435, 482, 529, 576, + 2982, 3304, 3626, 3948, + 20439, 22646, 24853, 27060}; + Matrix4 p2 = m2 * m1; + for (int i = 0; i < 16; i++) { + EXPECT_EQ(p2.CArray()[i], p2Expect[i]); + } + + /* Multiplication with the identity matrix produces the same matrix. */ + Matrix4 p3 = m1 * Matrix4::Identity(); + for (int i = 0; i < 16; i++) { + EXPECT_EQ(p3.CArray()[i], m1.CArray()[i]); + } + Matrix4 p4 = Matrix4::Identity() * m1; + for (int i = 0; i < 16; i++) { + EXPECT_EQ(p4.CArray()[i], m1.CArray()[i]); + } +} From 32b52ace9305afde53944b3696aa32d3f4b56cfc Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Fri, 8 Aug 2014 17:35:34 -0700 Subject: [PATCH 02/92] Templated matrix class --- src/basics/matrix.hh | 167 +++++++++++++++++++++++++++++++++++++++++++ src/basics/types.hh | 19 +++++ 2 files changed, 186 insertions(+) create mode 100644 src/basics/matrix.hh create mode 100644 src/basics/types.hh diff --git a/src/basics/matrix.hh b/src/basics/matrix.hh new file mode 100644 index 0000000..88ad95b --- /dev/null +++ b/src/basics/matrix.hh @@ -0,0 +1,167 @@ +/* matrix.hh + * vim: set tw=80: + * Eryn Wells + */ + +#ifndef __BASICS_MATRIX_HH__ +#define __BASICS_MATRIX_HH__ + +#include +#include +#include + +#include "basics/types.hh" + + +namespace charles { +namespace basics { + +/** + * A generic, templated Matrix class taking two template parameters. `N` is the + * number of rows. `M` is the number of columns. + */ +template +struct Matrix +{ + /** Construct an N x M matrix of zeros. */ + static Matrix Zero(); + + /** Construct an N x M identity matrix. */ + static Matrix Identity(); + + /** Value accessor. Get the ij'th item. */ + Double& operator(uint i, uint j); + + /** Scalar multiplication */ + Matrix operator*(const Double& lhs) const; + + /** Matrix multiplication */ + template + Matrix operator*(Matrix lhs) const; + + const Double* CArray() const; + +private: + /** The matrix data, stored in row-major format. */ + Double mData[N * M]; +}; + + +/** Scalar multiplication, scalar factor on the left. */ +template +Matrix operator*(const Double& lhs, const Matrix& rhs); + + +/* + * charles::basics::Matrix<>::Zero -- + */ +template +Matrix +Matrix::Zero() +{ + Matrix m; + bzero(m.mData, sizeof(Double) * N * M); + return m; +} + + +/* + * charles::basics::Matrix<>::Identity -- + */ +template +Matrix +Matrix::Identity() +{ + static_assert(N == M, "Identity matrices must be square."); + + auto m = Matrix::Zero(); + for (int i = 0; i < N; i++) { + for (int j = 0; j < M; j++) { + if (i == j) { + m(i,j) = 1.0; + } + } + } + return m; +} + + +/* + * charles::basics::Matrix<>::operator() -- + */ +template +Double& +Matrix::operator()(uint i, uint j) +{ + assert(i < N && j < M); + return mData[i * N + j]; +} + + +/* + * charles::basics::Matrix<>::operator* -- + */ +template +Matrix +Matrix::operator*(const Double& lhs) + const +{ + Matrix result; + for (int i = 0; i < N*M; i++) { + result.mData = mData[i] * lhs; + } + return result; +} + + +/* + * charles::basics::Matrix<>::operator* -- + */ +template +template +Matrix +Matrix::operator*(Matrix lhs) + const +{ + Matrix result; + for (int i = 0; i < N; i++) { + for (int j = 0; j < P; j++) { + /* Each cell is Sigma(k=0, M)(lhs[ik] * rhs[kj]) */ + const int ij = i*N + j; + mCells[ij] = 0.0; + for (int k = 0; k < M; k++) { + result.mCells[ij] += mCells[i*N + k] * rhs.mCells[k*P + j]; + } + } + } + return result; +} + + +/* + * charles::basics::Matrix<>::CArray -- + */ +template +const Double* +Matrix::CArray() + const +{ + return mData; +} + + +/* + * charles::basics::operator* -- + */ +template +Matrix +operator*(const Double& lhs, + const Matrix& rhs) +{ + return rhs * lhs; +} + +} /* namespace basics */ +} /* namespace charles */ + +#endif /* __BASICS_MATRIX_HH__ */ diff --git a/src/basics/types.hh b/src/basics/types.hh new file mode 100644 index 0000000..5b20021 --- /dev/null +++ b/src/basics/types.hh @@ -0,0 +1,19 @@ +/* types.hh + * vim: set tw=80: + * Eryn Wells + */ +/** + * Some basic types. + */ + +#ifndef __BASICS_TYPES_HH__ +#define __BASICS_TYPES_HH__ + +typedef double Double; + +typedef unsigned int uint; + +typedef std::vector DoubleVector; +typedef DoubleVector TVector; + +#endif /* __BASICS_TYPES_HH__ */ From 064ee2e4f17b03cbd8c026b5a8e6414dfd067b3b Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Fri, 8 Aug 2014 17:38:05 -0700 Subject: [PATCH 03/92] Include in basics types.hh --- src/basics/types.hh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/basics/types.hh b/src/basics/types.hh index 5b20021..68fb85a 100644 --- a/src/basics/types.hh +++ b/src/basics/types.hh @@ -9,6 +9,9 @@ #ifndef __BASICS_TYPES_HH__ #define __BASICS_TYPES_HH__ +#include + + typedef double Double; typedef unsigned int uint; From a9c8d84ac2be388564efdc597d451d62413d03ab Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Fri, 8 Aug 2014 17:38:13 -0700 Subject: [PATCH 04/92] Top-level include for basics --- src/basics/basics.hh | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100644 src/basics/basics.hh diff --git a/src/basics/basics.hh b/src/basics/basics.hh new file mode 100644 index 0000000..838bbcd --- /dev/null +++ b/src/basics/basics.hh @@ -0,0 +1,24 @@ +/* basics.hh + * vim: set tw=80: + * Eryn Wells + */ +/** + * Top-level include for the basics module. + */ + +#ifndef __BASICS_BASICS_HH__ +#define __BASICS_BASICS_HH__ + +#include "matrix.hh" +#include "types.hh" + + +namespace charles { +namespace basics { + +typedef Matrix<4,4> Matrix4; + +} /* namespace basics */ +} /* namespace charles */ + +#endif /* __BASICS_BASICS_HH__ */ From c5b9d73a9690dbbce1ef240c9e645eda7bf8c26c Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Fri, 8 Aug 2014 20:44:31 -0700 Subject: [PATCH 05/92] Add constructors and operator== to Matrix<> --- src/basics/basics.hh | 4 +- src/basics/matrix.hh | 103 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 97 insertions(+), 10 deletions(-) diff --git a/src/basics/basics.hh b/src/basics/basics.hh index 838bbcd..96b8aa2 100644 --- a/src/basics/basics.hh +++ b/src/basics/basics.hh @@ -9,8 +9,8 @@ #ifndef __BASICS_BASICS_HH__ #define __BASICS_BASICS_HH__ -#include "matrix.hh" -#include "types.hh" +#include "basics/matrix.hh" +#include "basics/types.hh" namespace charles { diff --git a/src/basics/matrix.hh b/src/basics/matrix.hh index 88ad95b..84c53a2 100644 --- a/src/basics/matrix.hh +++ b/src/basics/matrix.hh @@ -18,27 +18,42 @@ namespace basics { /** * A generic, templated Matrix class taking two template parameters. `N` is the - * number of rows. `M` is the number of columns. + * number of rows. `M` is the number of columns. If `M` is not specified, the + * matrix will be square. */ -template +template struct Matrix { /** Construct an N x M matrix of zeros. */ static Matrix Zero(); - /** Construct an N x M identity matrix. */ + /** + * Construct an N x M identity matrix. Identity matrices are always square. + * It is a (compile time) error to call Identity on a Matrix class where + * N != M. + */ static Matrix Identity(); + Matrix(); + Matrix(const Double data[N*M]); + Matrix(const Matrix& rhs); + + Matrix& operator=(const Matrix& rhs); + + bool operator==(const Matrix& rhs); + bool operator!=(const Matrix& rhs); + /** Value accessor. Get the ij'th item. */ Double& operator(uint i, uint j); /** Scalar multiplication */ - Matrix operator*(const Double& lhs) const; + Matrix operator*(const Double& rhs) const; /** Matrix multiplication */ template - Matrix operator*(Matrix lhs) const; + Matrix operator*(Matrix rhs) const; + /** Get the underlying C array */ const Double* CArray() const; private: @@ -47,11 +62,83 @@ private: }; +typedef Matrix<4> Matrix4; + + /** Scalar multiplication, scalar factor on the left. */ template Matrix operator*(const Double& lhs, const Matrix& rhs); +/* + * charles::basics::Matrix<>::Matrix -- + */ +template +Matrix::Matrix() + : mData() +{ } + + +/* + * charles::basics::Matrix<>::Matrix -- + */ +template +Matrix::Matrix(const Double data[N*M]) +{ + memcpy(mData, data, sizeof(Double) * N * M); +} + + +/* + * charles::basics::Matrix<>::Matrix -- + */ +template +Matrix::Matrix(const Matrix& rhs) + : Matrix(rhs.mData) +{ } + + +/* + * charles::basics::Matrix<>::operator= -- + */ +template +Matrix& +Matrix::operator=(const Matrix& rhs) +{ + memcpy(mData, rhs.mData, sizeof(Double) * N * M); + return *this; +} + + +/* + * charles::basics::Matrix<>::operator== -- + */ +template +bool +Matrix::operator==(const Matrix& rhs) + const +{ + for (int i = 0; i < N*M; i++) { + if (mData[i] != rhs.mData[i]) { + return false; + } + } + return true; +} + + +/* + * charles::basics::Matrix<>::operator!= -- + */ +template +bool +Matrix::operator!=(const Matrix& rhs) + const +{ + return !(*this == rhs); +} + + /* * charles::basics::Matrix<>::Zero -- */ @@ -103,12 +190,12 @@ Matrix::operator()(uint i, uint j) */ template Matrix -Matrix::operator*(const Double& lhs) +Matrix::operator*(const Double& rhs) const { Matrix result; for (int i = 0; i < N*M; i++) { - result.mData = mData[i] * lhs; + result.mData = mData[i] * rhs; } return result; } @@ -120,7 +207,7 @@ Matrix::operator*(const Double& lhs) template template Matrix -Matrix::operator*(Matrix lhs) +Matrix::operator*(Matrix rhs) const { Matrix result; From 3b713856dbb5c43189d91c07068bbf1d7bc565fe Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Fri, 8 Aug 2014 20:44:43 -0700 Subject: [PATCH 06/92] Vector, a single-column Matrix --- src/basics/vector.hh | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 src/basics/vector.hh diff --git a/src/basics/vector.hh b/src/basics/vector.hh new file mode 100644 index 0000000..b16c103 --- /dev/null +++ b/src/basics/vector.hh @@ -0,0 +1,28 @@ +/* vector.hh + * vim: set tw=80: + * Eryn Wells + */ + +#ifndef __BASICS_VECTOR_HH__ +#define __BASICS_VECTOR_HH__ + +#include "basics/matrix.hh" +#include "basics/types.hh" + + +namespace charles { +namespace basics { + +template +struct Vector + : public Matrix +{ }; + + +typedef Vector<4> Vector4; + +} /* namespace basics */ +} /* namespace charles */ + +#endif /* __BASICS_VECTOR_HH__ */ + From bfd3b8cbced0e2a13b43c95bf73add0bfa0580b5 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Fri, 8 Aug 2014 21:12:06 -0700 Subject: [PATCH 07/92] =?UTF-8?q?uint=20=E2=80=93>=20UInt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/basics/matrix.hh | 41 +++++++++++++++++++++-------------------- src/basics/types.hh | 3 +-- 2 files changed, 22 insertions(+), 22 deletions(-) diff --git a/src/basics/matrix.hh b/src/basics/matrix.hh index 84c53a2..aa09535 100644 --- a/src/basics/matrix.hh +++ b/src/basics/matrix.hh @@ -21,7 +21,7 @@ namespace basics { * number of rows. `M` is the number of columns. If `M` is not specified, the * matrix will be square. */ -template +template struct Matrix { /** Construct an N x M matrix of zeros. */ @@ -44,19 +44,19 @@ struct Matrix bool operator!=(const Matrix& rhs); /** Value accessor. Get the ij'th item. */ - Double& operator(uint i, uint j); + Double& operator()(UInt i, UInt j); /** Scalar multiplication */ Matrix operator*(const Double& rhs) const; /** Matrix multiplication */ - template + template Matrix operator*(Matrix rhs) const; /** Get the underlying C array */ const Double* CArray() const; -private: +protected: /** The matrix data, stored in row-major format. */ Double mData[N * M]; }; @@ -66,14 +66,14 @@ typedef Matrix<4> Matrix4; /** Scalar multiplication, scalar factor on the left. */ -template +template Matrix operator*(const Double& lhs, const Matrix& rhs); /* * charles::basics::Matrix<>::Matrix -- */ -template +template Matrix::Matrix() : mData() { } @@ -82,7 +82,7 @@ Matrix::Matrix() /* * charles::basics::Matrix<>::Matrix -- */ -template +template Matrix::Matrix(const Double data[N*M]) { memcpy(mData, data, sizeof(Double) * N * M); @@ -92,7 +92,7 @@ Matrix::Matrix(const Double data[N*M]) /* * charles::basics::Matrix<>::Matrix -- */ -template +template Matrix::Matrix(const Matrix& rhs) : Matrix(rhs.mData) { } @@ -101,7 +101,7 @@ Matrix::Matrix(const Matrix& rhs) /* * charles::basics::Matrix<>::operator= -- */ -template +template Matrix& Matrix::operator=(const Matrix& rhs) { @@ -113,12 +113,13 @@ Matrix::operator=(const Matrix& rhs) /* * charles::basics::Matrix<>::operator== -- */ -template +template bool Matrix::operator==(const Matrix& rhs) const { for (int i = 0; i < N*M; i++) { + /* TODO: Use NearlyEqual. */ if (mData[i] != rhs.mData[i]) { return false; } @@ -130,7 +131,7 @@ Matrix::operator==(const Matrix& rhs) /* * charles::basics::Matrix<>::operator!= -- */ -template +template bool Matrix::operator!=(const Matrix& rhs) const @@ -142,7 +143,7 @@ Matrix::operator!=(const Matrix& rhs) /* * charles::basics::Matrix<>::Zero -- */ -template +template Matrix Matrix::Zero() { @@ -155,7 +156,7 @@ Matrix::Zero() /* * charles::basics::Matrix<>::Identity -- */ -template +template Matrix Matrix::Identity() { @@ -176,9 +177,9 @@ Matrix::Identity() /* * charles::basics::Matrix<>::operator() -- */ -template +template Double& -Matrix::operator()(uint i, uint j) +Matrix::operator()(UInt i, UInt j) { assert(i < N && j < M); return mData[i * N + j]; @@ -188,7 +189,7 @@ Matrix::operator()(uint i, uint j) /* * charles::basics::Matrix<>::operator* -- */ -template +template Matrix Matrix::operator*(const Double& rhs) const @@ -204,8 +205,8 @@ Matrix::operator*(const Double& rhs) /* * charles::basics::Matrix<>::operator* -- */ -template -template +template +template Matrix Matrix::operator*(Matrix rhs) const @@ -228,7 +229,7 @@ Matrix::operator*(Matrix rhs) /* * charles::basics::Matrix<>::CArray -- */ -template +template const Double* Matrix::CArray() const @@ -240,7 +241,7 @@ Matrix::CArray() /* * charles::basics::operator* -- */ -template +template Matrix operator*(const Double& lhs, const Matrix& rhs) diff --git a/src/basics/types.hh b/src/basics/types.hh index 68fb85a..e847353 100644 --- a/src/basics/types.hh +++ b/src/basics/types.hh @@ -13,8 +13,7 @@ typedef double Double; - -typedef unsigned int uint; +typedef unsigned int UInt; typedef std::vector DoubleVector; typedef DoubleVector TVector; From 2b9fec5d82b6aea5dfd0720ab1c3651f844bb1c4 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Fri, 8 Aug 2014 21:12:18 -0700 Subject: [PATCH 08/92] Const operator== --- src/basics/matrix.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/basics/matrix.hh b/src/basics/matrix.hh index aa09535..d5bc64f 100644 --- a/src/basics/matrix.hh +++ b/src/basics/matrix.hh @@ -40,8 +40,8 @@ struct Matrix Matrix& operator=(const Matrix& rhs); - bool operator==(const Matrix& rhs); - bool operator!=(const Matrix& rhs); + bool operator==(const Matrix& rhs) const; + bool operator!=(const Matrix& rhs) const; /** Value accessor. Get the ij'th item. */ Double& operator()(UInt i, UInt j); From da127ccde3a7e237b2ae44f547486534a1175b12 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Fri, 8 Aug 2014 21:12:37 -0700 Subject: [PATCH 09/92] Vector4 subclass instead of typedef --- src/basics/vector.cc | 50 ++++++++++++++++++++++++++++++++++++++++++++ src/basics/vector.hh | 11 +++++++++- 2 files changed, 60 insertions(+), 1 deletion(-) create mode 100644 src/basics/vector.cc diff --git a/src/basics/vector.cc b/src/basics/vector.cc new file mode 100644 index 0000000..31842b8 --- /dev/null +++ b/src/basics/vector.cc @@ -0,0 +1,50 @@ +/* vector.cc + * vim: set tw=80: + * Eryn Wells + */ + +#include "basics/vector.hh" + + +namespace charles { +namespace basics { + +Vector4::Vector4() + : mCells({0.0, 0.0, 0.0, 1.0}) +{ + +} + + +/* + * charles::basics::Vector4::X -- + */ +Double& +Vector4::X() +{ + return mData[0]; +} + + +/* + * charles::basics::Vector4::Y -- + */ +Double& +Vector4::Y() +{ + return mData[1]; +} + + +/* + * charles::basics::Vector4::Z -- + */ +Double& +Vector4::Z() +{ + return mData[2]; +} + +} /* namespace basics */ +} /* namespace charles */ + diff --git a/src/basics/vector.hh b/src/basics/vector.hh index b16c103..c383b19 100644 --- a/src/basics/vector.hh +++ b/src/basics/vector.hh @@ -19,7 +19,16 @@ struct Vector { }; -typedef Vector<4> Vector4; +struct Vector4 + : public Vector<4> +{ + Vector4(); + Vector4(Double x, Double y, Double z); + + Double& X(); + Double& Y(); + Double& Z(); +}; } /* namespace basics */ } /* namespace charles */ From 3bf72bd78da8fcfa4423ec4e94a86c7d0507da5c Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Fri, 8 Aug 2014 21:12:44 -0700 Subject: [PATCH 10/92] Build basics! --- src/SConscript | 1 + src/basics/SConscript | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 src/basics/SConscript diff --git a/src/SConscript b/src/SConscript index a3dffe4..e0cb024 100644 --- a/src/SConscript +++ b/src/SConscript @@ -8,6 +8,7 @@ Import('env') objs = [] subdirs = [ + 'basics', 'yaml', ] diff --git a/src/basics/SConscript b/src/basics/SConscript new file mode 100644 index 0000000..873ba8c --- /dev/null +++ b/src/basics/SConscript @@ -0,0 +1,13 @@ +# SConscript +# vim: set ft=python: +# Eryn Wells + +Import('env') + + +files = [ + 'vector.cc', +] + +objs = [env.Object(f) for f in files] +Return('objs') From 2cadffd7d40867dc450d110dc845051cdf1dde12 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Fri, 8 Aug 2014 21:47:44 -0700 Subject: [PATCH 11/92] Fix Vector4 constructors and clean up compiler errors --- src/basics/basics.hh | 4 +++- src/basics/matrix.hh | 6 +++--- src/basics/vector.cc | 19 +++++++++++++++++-- src/basics/vector.hh | 4 ++-- 4 files changed, 25 insertions(+), 8 deletions(-) diff --git a/src/basics/basics.hh b/src/basics/basics.hh index 96b8aa2..34c9f61 100644 --- a/src/basics/basics.hh +++ b/src/basics/basics.hh @@ -11,12 +11,14 @@ #include "basics/matrix.hh" #include "basics/types.hh" +#include "basics/vector.hh" namespace charles { namespace basics { -typedef Matrix<4,4> Matrix4; +/** A 4-square matrix */ +typedef Matrix<4> Matrix4; } /* namespace basics */ } /* namespace charles */ diff --git a/src/basics/matrix.hh b/src/basics/matrix.hh index d5bc64f..14c37ec 100644 --- a/src/basics/matrix.hh +++ b/src/basics/matrix.hh @@ -27,7 +27,7 @@ struct Matrix /** Construct an N x M matrix of zeros. */ static Matrix Zero(); - /** + /** * Construct an N x M identity matrix. Identity matrices are always square. * It is a (compile time) error to call Identity on a Matrix class where * N != M. @@ -216,9 +216,9 @@ Matrix::operator*(Matrix rhs) for (int j = 0; j < P; j++) { /* Each cell is Sigma(k=0, M)(lhs[ik] * rhs[kj]) */ const int ij = i*N + j; - mCells[ij] = 0.0; + mData[ij] = 0.0; for (int k = 0; k < M; k++) { - result.mCells[ij] += mCells[i*N + k] * rhs.mCells[k*P + j]; + result.mData[ij] += mData[i*N + k] * rhs.mData[k*P + j]; } } } diff --git a/src/basics/vector.cc b/src/basics/vector.cc index 31842b8..d9c2c73 100644 --- a/src/basics/vector.cc +++ b/src/basics/vector.cc @@ -9,10 +9,25 @@ namespace charles { namespace basics { +/* + * charles::basics::Vector4::Vector4 -- + */ Vector4::Vector4() - : mCells({0.0, 0.0, 0.0, 1.0}) -{ + : Vector4(0, 0, 0) +{ } + +/* + * charles::basics::Vector4::Vector4 -- + */ +Vector4::Vector4(const Double& x, + const Double& y, + const Double& z) +{ + mData[0] = x; + mData[1] = y; + mData[2] = z; + mData[3] = 1.0; } diff --git a/src/basics/vector.hh b/src/basics/vector.hh index c383b19..3c8f8ff 100644 --- a/src/basics/vector.hh +++ b/src/basics/vector.hh @@ -13,7 +13,7 @@ namespace charles { namespace basics { -template +template struct Vector : public Matrix { }; @@ -23,7 +23,7 @@ struct Vector4 : public Vector<4> { Vector4(); - Vector4(Double x, Double y, Double z); + Vector4(const Double& x, const Double& y, const Double& z); Double& X(); Double& Y(); From 9474153736760d870f28b5335cce755233f4e5d2 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Fri, 8 Aug 2014 22:13:51 -0700 Subject: [PATCH 12/92] Move Zero() and Identity() definitions to the right place --- src/basics/matrix.hh | 64 +++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 34 deletions(-) diff --git a/src/basics/matrix.hh b/src/basics/matrix.hh index 14c37ec..127afcb 100644 --- a/src/basics/matrix.hh +++ b/src/basics/matrix.hh @@ -70,6 +70,36 @@ template Matrix operator*(const Double& lhs, const Matrix& rhs); +/* + * charles::basics::Matrix<>::Zero -- + */ +template +/* static */ Matrix +Matrix::Zero() +{ + Matrix m; + bzero(m.mData, sizeof(Double) * N * M); + return m; +} + + +/* + * charles::basics::Matrix<>::Identity -- + */ +template +/* static */ Matrix +Matrix::Identity() +{ + static_assert(N == M, "Identity matrices must be square."); + + auto m = Matrix::Zero(); + for (size_t i = 0; i < N; i++) { + m(i,i) = 1.0; + } + return m; +} + + /* * charles::basics::Matrix<>::Matrix -- */ @@ -140,40 +170,6 @@ Matrix::operator!=(const Matrix& rhs) } -/* - * charles::basics::Matrix<>::Zero -- - */ -template -Matrix -Matrix::Zero() -{ - Matrix m; - bzero(m.mData, sizeof(Double) * N * M); - return m; -} - - -/* - * charles::basics::Matrix<>::Identity -- - */ -template -Matrix -Matrix::Identity() -{ - static_assert(N == M, "Identity matrices must be square."); - - auto m = Matrix::Zero(); - for (int i = 0; i < N; i++) { - for (int j = 0; j < M; j++) { - if (i == j) { - m(i,j) = 1.0; - } - } - } - return m; -} - - /* * charles::basics::Matrix<>::operator() -- */ From b59b6d85c00294164b3a9ee56de6b03a82cdd9a7 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Fri, 8 Aug 2014 22:14:20 -0700 Subject: [PATCH 13/92] Add Matrix4, implement TranslationMatrix() --- src/basics/SConscript | 1 + src/basics/basics.hh | 10 ---------- src/basics/matrix.cc | 29 +++++++++++++++++++++++++++++ src/basics/matrix.hh | 7 +++++++ 4 files changed, 37 insertions(+), 10 deletions(-) create mode 100644 src/basics/matrix.cc diff --git a/src/basics/SConscript b/src/basics/SConscript index 873ba8c..0daa482 100644 --- a/src/basics/SConscript +++ b/src/basics/SConscript @@ -6,6 +6,7 @@ Import('env') files = [ + 'matrix.cc', 'vector.cc', ] diff --git a/src/basics/basics.hh b/src/basics/basics.hh index 34c9f61..8a556e8 100644 --- a/src/basics/basics.hh +++ b/src/basics/basics.hh @@ -13,14 +13,4 @@ #include "basics/types.hh" #include "basics/vector.hh" - -namespace charles { -namespace basics { - -/** A 4-square matrix */ -typedef Matrix<4> Matrix4; - -} /* namespace basics */ -} /* namespace charles */ - #endif /* __BASICS_BASICS_HH__ */ diff --git a/src/basics/matrix.cc b/src/basics/matrix.cc new file mode 100644 index 0000000..23b28ba --- /dev/null +++ b/src/basics/matrix.cc @@ -0,0 +1,29 @@ +/* matrix.cc + * vim: set tw=80: + * Eryn Wells + */ + +#include "matrix.hh" + + +namespace charles { +namespace basics { + +/* + * charles::basics::TranslationMatrix -- + */ +Matrix4 +TranslationMatrix(const Double& x, + const Double& y, + const Double& z) +{ + Matrix4 m = Matrix4::Identity(); + m(0, 3) = x; + m(1, 3) = y; + m(2, 3) = z; + return m; +} + +} /* namespace mespace */ +} /* namespace charles */ + diff --git a/src/basics/matrix.hh b/src/basics/matrix.hh index 127afcb..1bb0945 100644 --- a/src/basics/matrix.hh +++ b/src/basics/matrix.hh @@ -65,6 +65,13 @@ protected: typedef Matrix<4> Matrix4; +/** + * Create a translation matrix that will translate a vector to the given + * coordinates. + */ +static Matrix4 TranslationMatrix(const Double& x, const Double& y, const Double& z); + + /** Scalar multiplication, scalar factor on the left. */ template Matrix operator*(const Double& lhs, const Matrix& rhs); From abd38169b1e62674522275a305a5e124121f6b5d Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Fri, 8 Aug 2014 22:14:36 -0700 Subject: [PATCH 14/92] Comment out all the old Matrix4 stuff --- src/basics.cc | 2 ++ src/basics.h | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/basics.cc b/src/basics.cc index 7bfe278..1666c67 100644 --- a/src/basics.cc +++ b/src/basics.cc @@ -276,6 +276,7 @@ LinearCombination(const Double k1, const Vector3& v1, #pragma mark - Matrices +#if 0 /* static */ Matrix4 Matrix4::Zero() { @@ -488,6 +489,7 @@ operator*(const Double rhs, /* Scalar multiplication is commutative. */ return lhs * rhs; } +#endif #pragma mark - Rays diff --git a/src/basics.h b/src/basics.h index d915b60..2c57a79 100644 --- a/src/basics.h +++ b/src/basics.h @@ -119,6 +119,7 @@ Vector3 LinearCombination(const Double k1, const Vector3& v1, const Double k3, const Vector3& v3); +#if 0 struct Matrix4 { /** Create a 4x4 zero matrix. That is, all cells are 0. */ @@ -192,6 +193,7 @@ private: Matrix4 operator*(const Double lhs, const Matrix4& rhs); +#endif struct Ray From be15d553f1bf802f75837edd6c12d21c6db635e9 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Fri, 8 Aug 2014 23:04:52 -0700 Subject: [PATCH 15/92] Move EPSILON and MAX_DISTANCE to basics/basics.hh --- src/basics.h | 12 ------------ src/basics/basics.hh | 13 +++++++++++++ 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/basics.h b/src/basics.h index 2c57a79..0f535bc 100644 --- a/src/basics.h +++ b/src/basics.h @@ -18,18 +18,6 @@ using charles::Double; -/** - * A very small constant. If a value is between EPSILON and 0.0, it is - * considered to be zero. - */ -const Double EPSILON = 1.0e-10; - -/** - * The maximum distance a ray can travel. This is the maximum value t can be. - */ -const Double MAX_DISTANCE = 1.0e7; - - /** * Determine if the value is "close enough" to zero. Takes the absolute value * and compares it to `EPSILON`. diff --git a/src/basics/basics.hh b/src/basics/basics.hh index 8a556e8..4fd3a25 100644 --- a/src/basics/basics.hh +++ b/src/basics/basics.hh @@ -13,4 +13,17 @@ #include "basics/types.hh" #include "basics/vector.hh" + +/** + * A very small constant. If a value is between EPSILON and 0.0, it is + * considered to be zero. + */ +const Double EPSILON = 1.0e-10; + +/** + * The maximum distance a ray can travel. This is the maximum value t can be. + */ +const Double MAX_DISTANCE = 1.0e7; + + #endif /* __BASICS_BASICS_HH__ */ From 9b076f153329ea4a44800ef451c3a1ba5fc2d3b0 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Fri, 8 Aug 2014 23:05:24 -0700 Subject: [PATCH 16/92] Implement more robust * and / for Matrix --- src/basics/matrix.hh | 49 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 40 insertions(+), 9 deletions(-) diff --git a/src/basics/matrix.hh b/src/basics/matrix.hh index 1bb0945..5e7682f 100644 --- a/src/basics/matrix.hh +++ b/src/basics/matrix.hh @@ -48,6 +48,10 @@ struct Matrix /** Scalar multiplication */ Matrix operator*(const Double& rhs) const; + Matrix& operator*=(const Double& rhs); + + Matrix operator/(const Double& rhs) const; + Matrix& operator/=(const Double& rhs); /** Matrix multiplication */ template @@ -62,6 +66,12 @@ protected: }; +/** Scalar multiplication, scalar factor on the left. */ +template +Matrix operator*(const Double& lhs, const Matrix& rhs); + + +/** A standard 4x4 matrix. */ typedef Matrix<4> Matrix4; @@ -71,11 +81,7 @@ typedef Matrix<4> Matrix4; */ static Matrix4 TranslationMatrix(const Double& x, const Double& y, const Double& z); - -/** Scalar multiplication, scalar factor on the left. */ -template -Matrix operator*(const Double& lhs, const Matrix& rhs); - +#pragma mark Static Methods /* * charles::basics::Matrix<>::Zero -- @@ -106,6 +112,7 @@ Matrix::Identity() return m; } +#pragma mark Instance Methods /* * charles::basics::Matrix<>::Matrix -- @@ -197,11 +204,35 @@ Matrix Matrix::operator*(const Double& rhs) const { - Matrix result; - for (int i = 0; i < N*M; i++) { - result.mData = mData[i] * rhs; + return Matrix(*this) *= rhs; +} + + +template +Matrix& +Matrix::operator*=(const Double& rhs) +{ + for (size_t i = 0; i < N*M; i++) { + mData[i] *= rhs; } - return result; + return *this; +} + + +template +Matrix +Matrix::operator/(const Double& rhs) + const +{ + return Matrix(*this) /= rhs; +} + + +template +Matrix& +Matrix::operator/=(const Double& rhs) +{ + return *this *= (1.0 / rhs); } From fa3708edfb2f3fd4f375f90e97aa9ba4e5887b64 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Fri, 8 Aug 2014 23:05:38 -0700 Subject: [PATCH 17/92] Implement a bunch of the useful Vector operations --- src/basics/vector.cc | 46 ++++++++++++++++++++++++++++++++++++++++++++ src/basics/vector.hh | 19 ++++++++++++++++++ 2 files changed, 65 insertions(+) diff --git a/src/basics/vector.cc b/src/basics/vector.cc index d9c2c73..ded5a3e 100644 --- a/src/basics/vector.cc +++ b/src/basics/vector.cc @@ -3,6 +3,8 @@ * Eryn Wells */ +#include + #include "basics/vector.hh" @@ -60,6 +62,50 @@ Vector4::Z() return mData[2]; } + +/* + * charles::basics::Vector4::length2 -- + */ +Double +Vector4::Length2() + const +{ + return mData[0] * mData[0] + mData[1] * mData[1] + mData[2] * mData[2]; +} + + +Double +Vector4::Length() + const +{ + return std::sqrt(Length2()); +} + + +Double +Vector4::Dot(const Vector4& rhs) + const +{ + return mData[0] * rhs.mData[0] + mData[1] * rhs.mData[1] + mData[2] + rhs.mData[2]; +} + + +Vector4 +Vector4::Cross(const Vector4& rhs) + const +{ + return Vector4(mData[1]*rhs.mData[2] - mData[2]*rhs.mData[1], + mData[2]*rhs.mData[0] - mData[0]*rhs.mData[2], + mData[0]*rhs.mData[1] - mData[1]*rhs.mData[0]); +} + + +Vector4& +Vector4::Normalize() +{ + return *this /= Length(); +} + } /* namespace basics */ } /* namespace charles */ diff --git a/src/basics/vector.hh b/src/basics/vector.hh index 3c8f8ff..2ef9df4 100644 --- a/src/basics/vector.hh +++ b/src/basics/vector.hh @@ -28,8 +28,27 @@ struct Vector4 Double& X(); Double& Y(); Double& Z(); + + /** Get the length-squared of this vector. */ + Double Length2() const; + + /** Get the length of this vector. */ + Double Length() const; + + /** Get the dot product of `this` and `rhs`. */ + Double Dot(const Vector4& rhs) const; + + /** Get the cross product of `this` and `rhs`. */ + Vector4 Cross(const Vector4& rhs) const; + + /** Normalize this vector. */ + Vector4& Normalize(); }; + +/** Normalize the given vector and return a copy of it. */ +Vector4& Normalized(const Vector4& v); + } /* namespace basics */ } /* namespace charles */ From 32292a45fa52d1d92c8823e41196988ff3fa29ad Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 08:30:29 -0700 Subject: [PATCH 18/92] Move EPSILON and MAX_DISTANCE back to basics.h --- src/basics.h | 11 +++++++++++ src/basics/basics.hh | 13 ------------- 2 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/basics.h b/src/basics.h index 0f535bc..d703514 100644 --- a/src/basics.h +++ b/src/basics.h @@ -18,6 +18,17 @@ using charles::Double; +/** + * A very small constant. If a value is between EPSILON and 0.0, it is + * considered to be zero. + */ +const Double EPSILON = 1.0e-10; + +/** + * The maximum distance a ray can travel. This is the maximum value t can be. + */ +const Double MAX_DISTANCE = 1.0e7; + /** * Determine if the value is "close enough" to zero. Takes the absolute value * and compares it to `EPSILON`. diff --git a/src/basics/basics.hh b/src/basics/basics.hh index 4fd3a25..8a556e8 100644 --- a/src/basics/basics.hh +++ b/src/basics/basics.hh @@ -13,17 +13,4 @@ #include "basics/types.hh" #include "basics/vector.hh" - -/** - * A very small constant. If a value is between EPSILON and 0.0, it is - * considered to be zero. - */ -const Double EPSILON = 1.0e-10; - -/** - * The maximum distance a ray can travel. This is the maximum value t can be. - */ -const Double MAX_DISTANCE = 1.0e7; - - #endif /* __BASICS_BASICS_HH__ */ From cf57dfc51afbb67bc8dd9e5394fd0af6d55fae2e Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 08:31:25 -0700 Subject: [PATCH 19/92] I give up on Normalization Compiler was complaining about casting between Vector4 and Matrix<4,1> so I just did the division by hand. I bet operator* and operator/ are broken for Vector4s as well... --- src/basics/vector.cc | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/src/basics/vector.cc b/src/basics/vector.cc index ded5a3e..3984a3c 100644 --- a/src/basics/vector.cc +++ b/src/basics/vector.cc @@ -64,7 +64,7 @@ Vector4::Z() /* - * charles::basics::Vector4::length2 -- + * charles::basics::Vector4::Length2 -- */ Double Vector4::Length2() @@ -74,6 +74,9 @@ Vector4::Length2() } +/* + * charles::basics::Vector4::Length -- + */ Double Vector4::Length() const @@ -82,6 +85,9 @@ Vector4::Length() } +/* + * charles::basics::Vector4::Dot -- + */ Double Vector4::Dot(const Vector4& rhs) const @@ -90,6 +96,9 @@ Vector4::Dot(const Vector4& rhs) } +/* + * charles::basics::Vector4::Cross -- + */ Vector4 Vector4::Cross(const Vector4& rhs) const @@ -100,10 +109,18 @@ Vector4::Cross(const Vector4& rhs) } +/* + * charles::basics::Vector4::Normalize -- + */ Vector4& Vector4::Normalize() { - return *this /= Length(); + /* XXX: Is there some way to do this with the Matrix<>::operator/? */ + const Double len = Length(); + X() = X() / len; + Y() = Y() / len; + Z() = Z() / len; + return *this; } } /* namespace basics */ From 8ccfbc0498d7ee4c66a99ba8b12659b1c08ec865 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 08:31:37 -0700 Subject: [PATCH 20/92] Scalar multiplication Doxygen group --- src/basics/matrix.hh | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/basics/matrix.hh b/src/basics/matrix.hh index 5e7682f..22e1f1c 100644 --- a/src/basics/matrix.hh +++ b/src/basics/matrix.hh @@ -46,12 +46,15 @@ struct Matrix /** Value accessor. Get the ij'th item. */ Double& operator()(UInt i, UInt j); - /** Scalar multiplication */ + /** + * @defgroup Scalar multiplication + * @{ + */ Matrix operator*(const Double& rhs) const; Matrix& operator*=(const Double& rhs); - Matrix operator/(const Double& rhs) const; Matrix& operator/=(const Double& rhs); + /** @} */ /** Matrix multiplication */ template From ab9ac5e963c8636ba666710a21916ef435b12a90 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 08:57:41 -0700 Subject: [PATCH 21/92] Clean up constructors for Object and Sphere Use default arguments instead of multiple constructors. I forgot about those! Use Vector4s all around. --- src/object.cc | 28 +++++++++++----------------- src/object.h | 5 +++-- src/objectSphere.cc | 38 +++++++++++--------------------------- src/objectSphere.hh | 6 +++--- 4 files changed, 28 insertions(+), 49 deletions(-) diff --git a/src/object.cc b/src/object.cc index b74dcbe..866ffc3 100644 --- a/src/object.cc +++ b/src/object.cc @@ -12,32 +12,26 @@ #include "basics.h" #include "material.h" #include "object.h" +#include "basics/basics.hh" + + +using charles::basics::Vector4; + namespace charles { #pragma mark - Objects -/* - * Object::Object -- - * - * Default constructor. Create a new Object with an origin at (0, 0, 0). - */ -Object::Object() - : Object(Vector3::Zero) -{ } - - -/* - * Object::Object -- - * - * Constructor. Create a new Object with an origin at o. - */ -Object::Object(Vector3 origin) - : mOrigin(origin), +Object::Object(const Vector4& origin) + : mTranslation(basics::TranslationMatrix(origin.X(), origin.Y(), origin.Z())), mMaterial() { } +/* + */ + + Vector3 Object::GetOrigin() const diff --git a/src/object.h b/src/object.h index 4f906a7..4480edb 100644 --- a/src/object.h +++ b/src/object.h @@ -18,6 +18,8 @@ #include "stats.hh" #include "texture.h" #include "types.hh" +#include "basics/basics.hh" + namespace charles { @@ -25,8 +27,7 @@ struct Object { typedef std::shared_ptr Ptr; - Object(); - Object(Vector3 o); + Object(const basics::Vector4& origin = basics::Vector4()); virtual ~Object(); Vector3 GetOrigin() const; diff --git a/src/objectSphere.cc b/src/objectSphere.cc index 5adfb4d..d0ea008 100644 --- a/src/objectSphere.cc +++ b/src/objectSphere.cc @@ -14,32 +14,19 @@ #include "object.h" #include "objectSphere.hh" + +using charles::basics::Vector4; + + namespace charles { /* - * Sphere::Sphere -- - * - * Default constructor. Create a Sphere with radius 1.0. + * charles::Sphere::Sphere -- */ -Sphere::Sphere() - : Sphere(1.0) -{ } - - -/* - * Sphere::Sphere -- - * - * Constructor. Create a Sphere with the given radius. - */ -Sphere::Sphere(Double r) - : Sphere(Vector3::Zero, r) -{ } - - -Sphere::Sphere(Vector3 o, - Double r) - : Object(o), - mRadius(r) +Sphere::Sphere(const Vector4& origin, + Double radius) + : Object(origin), + mRadius(radius) { } @@ -69,13 +56,10 @@ Sphere::DoesIntersect(const Ray& ray, { stats.sphereIntersectionTests++; - /* Origin of the vector in object space. */ - Vector3 rayOriginObj = ray.origin - GetOrigin(); - /* Coefficients for quadratic equation. */ Double a = ray.direction.dot(ray.direction); - Double b = ray.direction.dot(rayOriginObj) * 2.0; - Double c = rayOriginObj.dot(rayOriginObj) - (mRadius * mRadius); + Double b = ray.direction.dot(ray.origin) * 2.0; + Double c = ray.origin.dot(ray.origin) - (mRadius * mRadius); /* Discriminant for the quadratic equation. */ Double discrim = (b * b) - (4.0 * a * c); diff --git a/src/objectSphere.hh b/src/objectSphere.hh index 12f9061..9597868 100644 --- a/src/objectSphere.hh +++ b/src/objectSphere.hh @@ -10,6 +10,8 @@ #include "basics.h" #include "object.h" +#include "basics/basics.hh" + namespace charles { @@ -17,9 +19,7 @@ class Sphere : public Object { public: - Sphere(); - Sphere(Double r); - Sphere(Vector3 o, Double r); + Sphere(const basics::Vector4& origin = basics::Vector4(), Double radius = 1.0); Double GetRadius() const; void SetRadius(Double r); From 584d0326a93911171507597026bedec36081ec23 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 08:59:11 -0700 Subject: [PATCH 22/92] Get rid of object's origin --- src/object.cc | 18 +----------------- src/object.h | 2 -- 2 files changed, 1 insertion(+), 19 deletions(-) diff --git a/src/object.cc b/src/object.cc index 866ffc3..22a173f 100644 --- a/src/object.cc +++ b/src/object.cc @@ -29,28 +29,12 @@ Object::Object(const Vector4& origin) /* + * charles::Object::~Object -- */ - - -Vector3 -Object::GetOrigin() - const -{ - return mOrigin; -} - - Object::~Object() { } -void -Object::SetOrigin(const Vector3& origin) -{ - mOrigin = origin; -} - - Material& Object::GetMaterial() { diff --git a/src/object.h b/src/object.h index 4480edb..c51f908 100644 --- a/src/object.h +++ b/src/object.h @@ -51,8 +51,6 @@ struct Object virtual void Write(std::ostream& ost) const; private: - /** The location of this object. */ - Vector3 mOrigin; /** This object's material, surface properties, etc. */ Material mMaterial; From 9b6b6a20b760f832f9f7807a8e8c1516060094e3 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 09:01:52 -0700 Subject: [PATCH 23/92] Const versions of Vector4's X(), Y(), and Z() --- src/basics/vector.cc | 23 +++++++++++++++++++++++ src/basics/vector.hh | 3 +++ 2 files changed, 26 insertions(+) diff --git a/src/basics/vector.cc b/src/basics/vector.cc index 3984a3c..e2913d5 100644 --- a/src/basics/vector.cc +++ b/src/basics/vector.cc @@ -42,6 +42,13 @@ Vector4::X() return mData[0]; } +const Double& +Vector4::X() + const +{ + return mData[0]; +} + /* * charles::basics::Vector4::Y -- @@ -53,6 +60,14 @@ Vector4::Y() } +const Double& +Vector4::Y() + const +{ + return mData[1]; +} + + /* * charles::basics::Vector4::Z -- */ @@ -63,6 +78,14 @@ Vector4::Z() } +const Double& +Vector4::Z() + const +{ + return mData[2]; +} + + /* * charles::basics::Vector4::Length2 -- */ diff --git a/src/basics/vector.hh b/src/basics/vector.hh index 2ef9df4..4440e69 100644 --- a/src/basics/vector.hh +++ b/src/basics/vector.hh @@ -26,8 +26,11 @@ struct Vector4 Vector4(const Double& x, const Double& y, const Double& z); Double& X(); + const Double& X() const; Double& Y(); + const Double& Y() const; Double& Z(); + const Double& Z() const; /** Get the length-squared of this vector. */ Double Length2() const; From a3d51f7cf387b541bcb0ad1c5b4ea6459e7d840a Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 09:02:04 -0700 Subject: [PATCH 24/92] TranslationMatrix() is not static --- src/basics/matrix.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/basics/matrix.hh b/src/basics/matrix.hh index 22e1f1c..b2dd107 100644 --- a/src/basics/matrix.hh +++ b/src/basics/matrix.hh @@ -82,7 +82,7 @@ typedef Matrix<4> Matrix4; * Create a translation matrix that will translate a vector to the given * coordinates. */ -static Matrix4 TranslationMatrix(const Double& x, const Double& y, const Double& z); +Matrix4 TranslationMatrix(const Double& x, const Double& y, const Double& z); #pragma mark Static Methods From b41cdb7186f48b995130a3074c53fa2fe096c7f7 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 09:32:48 -0700 Subject: [PATCH 25/92] Vector4 +, -, negation, and * +, -, and negation were easy. Multiplication is wacky because the Matrix class does it. So, to do binary * (not *=) I needed to dynamic_cast the resulting Matrix<4,1> to a Vector4&&. --- src/basics/vector.cc | 81 ++++++++++++++++++++++++++++++++++++++++++++ src/basics/vector.hh | 13 +++++++ 2 files changed, 94 insertions(+) diff --git a/src/basics/vector.cc b/src/basics/vector.cc index e2913d5..5f68bfa 100644 --- a/src/basics/vector.cc +++ b/src/basics/vector.cc @@ -78,6 +78,9 @@ Vector4::Z() } +/* + * charles::basics::Vector4::Z -- + */ const Double& Vector4::Z() const @@ -86,6 +89,73 @@ Vector4::Z() } +/* + * charles::basics::Vector4::operator* -- + */ +Vector4 +Vector4::operator*(const Double& rhs) + const +{ + return dynamic_cast(*this * rhs); +} + + +/* + * charles::basics::Vector4::operator+ -- + */ +Vector4 +Vector4::operator+(const Vector4& rhs) + const +{ + return Vector4(*this) += rhs; +} + + +/* + * charles::basics::Vector4::operator+= -- + */ +Vector4& +Vector4::operator+=(const Vector4& rhs) +{ + mData[0] += rhs.mData[0]; + mData[1] += rhs.mData[1]; + mData[2] += rhs.mData[2]; + return *this; +} + + +/* + * charles::basics::Vector4::operator- -- + */ +Vector4 +Vector4::operator-(const Vector4& rhs) + const +{ + return Vector4(*this) -= rhs; +} + + +/* + * charles::basics::Vector4::operator-= -- + */ +Vector4& +Vector4::operator-=(const Vector4& rhs) +{ + return *this += -rhs; +} + + +/* + * charles::basics::Vector4::operator- -- + */ +Vector4 +Vector4::operator-() + const +{ + return Vector4(-X(), -Y(), -Z()); +} + + /* * charles::basics::Vector4::Length2 -- */ @@ -146,6 +216,17 @@ Vector4::Normalize() return *this; } + +/* + * charles::basics::operator* -- + */ +Vector4 +operator*(const Double& lhs, + const Vector4& rhs) +{ + return rhs * lhs; +} + } /* namespace basics */ } /* namespace charles */ diff --git a/src/basics/vector.hh b/src/basics/vector.hh index 4440e69..9f34437 100644 --- a/src/basics/vector.hh +++ b/src/basics/vector.hh @@ -32,6 +32,15 @@ struct Vector4 Double& Z(); const Double& Z() const; + Vector4 operator*(const Double& rhs) const; + + Vector4 operator+(const Vector4& rhs) const; + Vector4& operator+=(const Vector4& rhs); + Vector4 operator-(const Vector4& rhs) const; + Vector4& operator-=(const Vector4& rhs); + + Vector4 operator-() const; + /** Get the length-squared of this vector. */ Double Length2() const; @@ -49,6 +58,10 @@ struct Vector4 }; +/** Scalar multiplication of vectors, with the scalar factor on the left. */ +Vector4 operator*(const Double& lhs, const Vector4& rhs); + + /** Normalize the given vector and return a copy of it. */ Vector4& Normalized(const Vector4& v); From 9aa557293ac3e7fe9f6b2121b4c5405e80fe07f4 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 09:33:22 -0700 Subject: [PATCH 26/92] A Ray class in basics! --- src/basics/SConscript | 1 + src/basics/basics.hh | 1 + src/basics/ray.cc | 35 +++++++++++++++++++++++++++++++++++ src/basics/ray.hh | 25 +++++++++++++++++++++++++ 4 files changed, 62 insertions(+) create mode 100644 src/basics/ray.cc create mode 100644 src/basics/ray.hh diff --git a/src/basics/SConscript b/src/basics/SConscript index 0daa482..2014565 100644 --- a/src/basics/SConscript +++ b/src/basics/SConscript @@ -7,6 +7,7 @@ Import('env') files = [ 'matrix.cc', + 'ray.cc', 'vector.cc', ] diff --git a/src/basics/basics.hh b/src/basics/basics.hh index 8a556e8..fb956cd 100644 --- a/src/basics/basics.hh +++ b/src/basics/basics.hh @@ -10,6 +10,7 @@ #define __BASICS_BASICS_HH__ #include "basics/matrix.hh" +#include "basics/ray.hh" #include "basics/types.hh" #include "basics/vector.hh" diff --git a/src/basics/ray.cc b/src/basics/ray.cc new file mode 100644 index 0000000..197de91 --- /dev/null +++ b/src/basics/ray.cc @@ -0,0 +1,35 @@ +/* ray.cc + * vim: set tw=80: + * Eryn Wells + */ + +#include "basics/ray.hh" + + +namespace charles { +namespace basics { + +/* + * charles::basics::Ray::Ray -- + */ +Ray::Ray(Vector4 o, + Vector4 d) + : origin(o), + direction(d) +{ } + + +/* + * charles::basics::Ray::Parameterize -- + */ +Vector4 +Ray::Parameterize(const Double& t) + const +{ + return origin + direction * t; +} + + +} /* namespace basics */ +} /* namespace charles */ + diff --git a/src/basics/ray.hh b/src/basics/ray.hh new file mode 100644 index 0000000..26057a3 --- /dev/null +++ b/src/basics/ray.hh @@ -0,0 +1,25 @@ +/* ray.hh + * vim: set tw=80: + * Eryn Wells + */ + +#include "basics/types.hh" +#include "basics/vector.hh" + + +namespace charles { +namespace basics { + +struct Ray +{ + Ray(Vector4 o = Vector4(), Vector4 d = Vector4()); + + Vector4 Parameterize(const Double& t) const; + + Vector4 origin; + Vector4 direction; +}; + +} /* namespace basics */ +} /* namespace charles */ + From 43cb182aa7991efb2d0d1e534f5bd366578836f0 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 09:57:09 -0700 Subject: [PATCH 27/92] Have to use operator() for Matrix<>::operator* Matrix is a different class from Matrix so Matrix can't access protected member data on Matrix. There must be a better way that having to do the multiplies requires for operator(). --- src/basics/matrix.hh | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/basics/matrix.hh b/src/basics/matrix.hh index b2dd107..b1d751b 100644 --- a/src/basics/matrix.hh +++ b/src/basics/matrix.hh @@ -249,13 +249,12 @@ Matrix::operator*(Matrix rhs) const { Matrix result; - for (int i = 0; i < N; i++) { - for (int j = 0; j < P; j++) { + for (UInt i = 0; i < N; i++) { + for (UInt j = 0; j < P; j++) { /* Each cell is Sigma(k=0, M)(lhs[ik] * rhs[kj]) */ - const int ij = i*N + j; - mData[ij] = 0.0; - for (int k = 0; k < M; k++) { - result.mData[ij] += mData[i*N + k] * rhs.mData[k*P + j]; + result(i, j) = 0.0; + for (UInt k = 0; k < M; k++) { + result(i, j) += mData[i*N + k] * rhs(k*P, j); } } } From 519eb347d194cec011fadd8f47a5dd488b2671bb Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 09:57:35 -0700 Subject: [PATCH 28/92] Vector4 constructor from Matrix<4,1> --- src/basics/vector.cc | 7 ++++++- src/basics/vector.hh | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/basics/vector.cc b/src/basics/vector.cc index 5f68bfa..314f026 100644 --- a/src/basics/vector.cc +++ b/src/basics/vector.cc @@ -33,6 +33,11 @@ Vector4::Vector4(const Double& x, } +Vector4::Vector4(const Matrix<4,1>&& rhs) + : Vector4(static_cast(rhs)) +{ } + + /* * charles::basics::Vector4::X -- */ @@ -96,7 +101,7 @@ Vector4 Vector4::operator*(const Double& rhs) const { - return dynamic_cast(*this * rhs); + return static_cast(*this * rhs); } diff --git a/src/basics/vector.hh b/src/basics/vector.hh index 9f34437..9ec4741 100644 --- a/src/basics/vector.hh +++ b/src/basics/vector.hh @@ -24,6 +24,7 @@ struct Vector4 { Vector4(); Vector4(const Double& x, const Double& y, const Double& z); + Vector4(const Matrix<4,1>&& m); Double& X(); const Double& X() const; From d0d667d6d2b3833ad72fee93776d55d07141b58f Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 09:59:00 -0700 Subject: [PATCH 29/92] Object::Intersect A new intersect method that converts to object space before doing the intersection. Now all objects are at their own origin! --- src/object.cc | 34 ++++++++++++++++++++++++++++++++++ src/object.h | 17 ++++++++++++++++- 2 files changed, 50 insertions(+), 1 deletion(-) diff --git a/src/object.cc b/src/object.cc index 22a173f..3b6ce8c 100644 --- a/src/object.cc +++ b/src/object.cc @@ -22,6 +22,9 @@ namespace charles { #pragma mark - Objects +/* + * charles::Object::Object -- + */ Object::Object(const Vector4& origin) : mTranslation(basics::TranslationMatrix(origin.X(), origin.Y(), origin.Z())), mMaterial() @@ -49,6 +52,37 @@ Object::SetMaterial(const Material& material) } +/* + * charles::Object::Intersect -- + */ +bool +Object::Intersect(const basics::Ray& ray, + TVector& t, + Stats& stats) + const +{ + /* TODO: Remove basics:: when the old Ray class goes away. */ + basics::Ray objRay = ToObjectSpace(ray); + return DoIntersect(objRay, t, stats); +} + + +/* + * charles::Object::ToObjectSpace -- + */ +/* TODO: Remove basics:: when the old Ray class goes away. */ +basics::Ray +Object::ToObjectSpace(const basics::Ray& ray) + const +{ + /* TODO: Remove basics:: when the old Ray class goes away. */ + basics::Ray objRay(ray); + objRay.origin = mTranslation * objRay.origin; + objRay.direction = mTranslation * objRay.direction; + return objRay; +} + + void Object::Write(std::ostream& ost) const diff --git a/src/object.h b/src/object.h index c51f908..c0d8071 100644 --- a/src/object.h +++ b/src/object.h @@ -37,7 +37,15 @@ struct Object void SetMaterial(const Material& material); /** - * Determines if the given ray intersects with this object. All intersection + * Determine if the given ray intersects with this object. Converts the + * ray's origin and direction to object space before calling the protected + * Object::DoIntersect method. All intersection t values are returned in the + * `t` argument, in ascending order. + */ + bool Intersect(const basics::Ray& ray, TVector& t, Stats& stats) const; + + /** + * Determine if the given ray intersects with this object. All intersection * t values are returned in the `t` argument, in increasing order. * * @param [in] ray The ray to test for intersection @@ -50,7 +58,14 @@ struct Object virtual void Write(std::ostream& ost) const; +protected: + virtual bool DoIntersect(const basics::Ray& ray, TVector& t, Stats& stats) const; + private: + basics::Ray ToObjectSpace(const basics::Ray& ray) const; + + /** A translation matrix from global coordinates to this object's space. */ + basics::Matrix4 mTranslation; /** This object's material, surface properties, etc. */ Material mMaterial; From 3846a1aa3a3b4b6738902d8ad158758597d292c5 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 10:08:21 -0700 Subject: [PATCH 30/92] Move Box intersection code to DoIntersect --- src/objectBox.cc | 105 ++++++++++++++++++++++++----------------------- src/objectBox.hh | 3 ++ 2 files changed, 57 insertions(+), 51 deletions(-) diff --git a/src/objectBox.cc b/src/objectBox.cc index ab818a0..17041ef 100644 --- a/src/objectBox.cc +++ b/src/objectBox.cc @@ -51,56 +51,6 @@ Box::SetFar(const Vector3& far) } -bool -Box::DoesIntersect(const Ray& ray, - TVector& t, - Stats& stats) - const -{ - stats.boxIntersectionTests++; - - /* - * XXX: For now, I'm assuming that all boxes are parallel to the coordinate - * axes. This is the Kay-Kajiya box intersection algorithm. - */ - - //Double t0, t1; - Double tNear = -std::numeric_limits::infinity(); - Double tFar = std::numeric_limits::infinity(); - - /* - * From the Ray Tracing book: - * - * For a more efficient algorithm, unwrap the loop, expand the swap of t0 - * and t1 into two branches, and change the calculations to multiply by - * the inverse of the ray's direction to avoid divisions. Unwrapping the - * loop allows elimination of comparing t0 adn t1 to tNear and tFar [for - * the X planes], as tNear will always be set to the smaller and tFar the - * larger of t0 and t1. - * - * Initially there was a for loop iterating over each parallel pair of - * planes (X, Y, and Z planes). - */ - - if (!IntersectSlab(mNear.x, mFar.x, ray.origin.x, ray.direction.x, tNear, tFar)) { - return false; - } - if (!IntersectSlab(mNear.y, mFar.y, ray.origin.y, ray.direction.y, tNear, tFar)) { - return false; - } - if (!IntersectSlab(mNear.z, mFar.z, ray.origin.z, ray.direction.z, tNear, tFar)) { - return false; - } - - /* We have an intersection! */ - stats.boxIntersections++; - t.push_back(tNear); - t.push_back(tFar); - - return true; -} - - bool Box::point_is_on_surface(const Vector3& p) const @@ -142,6 +92,44 @@ Box::compute_normal(const Vector3& p) } +/* + * charles::Box::DoIntersect -- + */ +bool +Box::DoIntersect(const basics::Ray& ray, + TVector& t, + Stats& stats) + const +{ + stats.boxIntersectionTests++; + + /* This is the Kay-Kajiya box intersection algorithm. */ + + Double tNear = -std::numeric_limits::infinity(); + Double tFar = std::numeric_limits::infinity(); + + if (!IntersectSlab(mNear.x, mFar.x, ray.origin.x, ray.direction.x, tNear, tFar)) { + return false; + } + if (!IntersectSlab(mNear.y, mFar.y, ray.origin.y, ray.direction.y, tNear, tFar)) { + return false; + } + if (!IntersectSlab(mNear.z, mFar.z, ray.origin.z, ray.direction.z, tNear, tFar)) { + return false; + } + + /* We have an intersection! */ + stats.boxIntersections++; + t.push_back(tNear); + t.push_back(tFar); + + return true; +} + + +/* + * charles::Box::IntersectSlab -- + */ inline bool Box::IntersectSlab(const Double& slabLow, const Double& slabHigh, @@ -153,6 +141,20 @@ Box::IntersectSlab(const Double& slabLow, { Double t0, t1; + /* + * From the Ray Tracing book: + * + * For a more efficient algorithm, unwrap the loop, expand the swap of t0 + * and t1 into two branches, and change the calculations to multiply by + * the inverse of the ray's direction to avoid divisions. Unwrapping the + * loop allows elimination of comparing t0 adn t1 to tNear and tFar [for + * the X planes], as tNear will always be set to the smaller and tFar the + * larger of t0 and t1. + * + * Initially there was a for loop iterating over each parallel pair of + * planes (X, Y, and Z planes). + */ + if (NearZero(rayDirectionComponent)) { /* The ray is parallel to the X axis. */ if (rayOriginComponent < slabLow || rayOriginComponent > slabHigh) { @@ -170,12 +172,13 @@ Box::IntersectSlab(const Double& slabLow, tNear = t1; tFar = t0; } -#endif +#else if (t0 > t1) { Double tmp = t0; t0 = t1; t1 = tmp; } +#endif if (t0 > tNear) { tNear = t0; } diff --git a/src/objectBox.hh b/src/objectBox.hh index 155f1c3..51a7281 100644 --- a/src/objectBox.hh +++ b/src/objectBox.hh @@ -28,6 +28,9 @@ struct Box /** @see charles::Object::Write */ void Write(std::ostream& ost) const; +protected: + bool DoIntersect(const basics::Ray& ray, TVector& t, Stats& stats) const; + private: /** * Perform the intersection test on a slab, defined by `slabHigh` and From baf40143b286acbccce93f2c9ca735db1fe1f5fd Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 10:08:29 -0700 Subject: [PATCH 31/92] DoIntersect is an abstract method --- src/object.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/object.h b/src/object.h index c0d8071..1fcb2d8 100644 --- a/src/object.h +++ b/src/object.h @@ -59,7 +59,7 @@ struct Object virtual void Write(std::ostream& ost) const; protected: - virtual bool DoIntersect(const basics::Ray& ray, TVector& t, Stats& stats) const; + virtual bool DoIntersect(const basics::Ray& ray, TVector& t, Stats& stats) const = 0; private: basics::Ray ToObjectSpace(const basics::Ray& ray) const; From 217c4709aad8d076de659e7690cf6ada243ab5a3 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 10:08:44 -0700 Subject: [PATCH 32/92] Vector4's constructor takes default arguments --- src/basics/vector.cc | 8 -------- src/basics/vector.hh | 3 +-- 2 files changed, 1 insertion(+), 10 deletions(-) diff --git a/src/basics/vector.cc b/src/basics/vector.cc index 314f026..a2d65f8 100644 --- a/src/basics/vector.cc +++ b/src/basics/vector.cc @@ -11,14 +11,6 @@ namespace charles { namespace basics { -/* - * charles::basics::Vector4::Vector4 -- - */ -Vector4::Vector4() - : Vector4(0, 0, 0) -{ } - - /* * charles::basics::Vector4::Vector4 -- */ diff --git a/src/basics/vector.hh b/src/basics/vector.hh index 9ec4741..4069d87 100644 --- a/src/basics/vector.hh +++ b/src/basics/vector.hh @@ -22,8 +22,7 @@ struct Vector struct Vector4 : public Vector<4> { - Vector4(); - Vector4(const Double& x, const Double& y, const Double& z); + Vector4(const Double& x = 0.0, const Double& y = 0.0, const Double& z = 0.0); Vector4(const Matrix<4,1>&& m); Double& X(); From 2c2bf091409f124946cc63ec3e1fe56d9f59dde1 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 10:11:44 -0700 Subject: [PATCH 33/92] Compiler errors in Box::DoIntersect, hidden until now... --- src/objectBox.cc | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/src/objectBox.cc b/src/objectBox.cc index 17041ef..f194a1a 100644 --- a/src/objectBox.cc +++ b/src/objectBox.cc @@ -108,13 +108,19 @@ Box::DoIntersect(const basics::Ray& ray, Double tNear = -std::numeric_limits::infinity(); Double tFar = std::numeric_limits::infinity(); - if (!IntersectSlab(mNear.x, mFar.x, ray.origin.x, ray.direction.x, tNear, tFar)) { + if (!IntersectSlab(mNear.x, mFar.x, + ray.origin.X(), ray.direction.X(), + tNear, tFar)) { return false; } - if (!IntersectSlab(mNear.y, mFar.y, ray.origin.y, ray.direction.y, tNear, tFar)) { + if (!IntersectSlab(mNear.y, mFar.y, + ray.origin.Y(), ray.direction.Y(), + tNear, tFar)) { return false; } - if (!IntersectSlab(mNear.z, mFar.z, ray.origin.z, ray.direction.z, tNear, tFar)) { + if (!IntersectSlab(mNear.z, mFar.z, + ray.origin.Z(), ray.direction.Z(), + tNear, tFar)) { return false; } @@ -199,6 +205,9 @@ Box::IntersectSlab(const Double& slabLow, } +/* + * charles::Box::Write -- + */ void Box::Write(std::ostream& ost) const From 70576c382aad7f55514d015b00367be15d76189f Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 10:42:49 -0700 Subject: [PATCH 34/92] Do all the clean up needed for Object --- src/object.cc | 64 ++++++++++++++++++++++++++++++------- src/{object.h => object.hh} | 47 +++++++++++++-------------- 2 files changed, 75 insertions(+), 36 deletions(-) rename src/{object.h => object.hh} (57%) diff --git a/src/object.cc b/src/object.cc index 3b6ce8c..3537d49 100644 --- a/src/object.cc +++ b/src/object.cc @@ -9,19 +9,18 @@ #include #include -#include "basics.h" +#include "object.hh" + #include "material.h" -#include "object.h" #include "basics/basics.hh" +using charles::basics::Ray; using charles::basics::Vector4; namespace charles { -#pragma mark - Objects - /* * charles::Object::Object -- */ @@ -38,6 +37,9 @@ Object::~Object() { } +/* + * charles::Object::GetMaterial -- + */ Material& Object::GetMaterial() { @@ -45,6 +47,9 @@ Object::GetMaterial() } +/* + * charles::Object::SetMaterial -- + */ void Object::SetMaterial(const Material& material) { @@ -61,28 +66,60 @@ Object::Intersect(const basics::Ray& ray, Stats& stats) const { - /* TODO: Remove basics:: when the old Ray class goes away. */ - basics::Ray objRay = ToObjectSpace(ray); - return DoIntersect(objRay, t, stats); + return DoIntersect(ToObjectSpace(ray), t, stats); +} + + +/* + * charles::Object::Normal -- + */ +Vector4 +Object::Normal(const Vector4& p) + const +{ + return FromObjectSpace(DoNormal(ToObjectSpace(p))); } /* * charles::Object::ToObjectSpace -- */ -/* TODO: Remove basics:: when the old Ray class goes away. */ -basics::Ray -Object::ToObjectSpace(const basics::Ray& ray) +Ray +Object::ToObjectSpace(const Ray& ray) const { - /* TODO: Remove basics:: when the old Ray class goes away. */ - basics::Ray objRay(ray); + Ray objRay(ray); objRay.origin = mTranslation * objRay.origin; objRay.direction = mTranslation * objRay.direction; return objRay; } +/* + * charles::Object::ToObjectSpace -- + */ +Vector4 +Object::ToObjectSpace(const Vector4& v) + const +{ + return mTranslation * v; +} + + +/* + * charles::Object::FromObjectSpace -- + */ +Vector4 +Object::FromObjectSpace(const Vector4& v) + const +{ + return v; +} + + +/* + * charles::Object::Write -- + */ void Object::Write(std::ostream& ost) const @@ -91,6 +128,9 @@ Object::Write(std::ostream& ost) } +/* + * charles::operator<< -- + */ std::ostream& operator<<(std::ostream& ost, const Object& object) diff --git a/src/object.h b/src/object.hh similarity index 57% rename from src/object.h rename to src/object.hh index 1fcb2d8..4ac3225 100644 --- a/src/object.h +++ b/src/object.hh @@ -1,8 +1,5 @@ /* object.h - * - * Declaration of abstract, top-level scene objects. The Object class is the top of this hierarchy. All other scene - * objects are based on it. The Shape class defines a visible shape in the scene. - * + * vim: set tw=80: * Eryn Wells */ @@ -13,7 +10,6 @@ #include #include -#include "basics.h" #include "material.h" #include "stats.hh" #include "texture.h" @@ -30,9 +26,6 @@ struct Object Object(const basics::Vector4& origin = basics::Vector4()); virtual ~Object(); - Vector3 GetOrigin() const; - void SetOrigin(const Vector3& origin); - Material& GetMaterial(); void SetMaterial(const Material& material); @@ -45,25 +38,37 @@ struct Object bool Intersect(const basics::Ray& ray, TVector& t, Stats& stats) const; /** - * Determine if the given ray intersects with this object. All intersection - * t values are returned in the `t` argument, in increasing order. - * - * @param [in] ray The ray to test for intersection - * @param [out] t A vector of all intersection t values - * @return `true` if the ray intersects with this object + * Get the normal vector at the given point p. p is assumed to be on the + * surface. */ - virtual bool DoesIntersect(const Ray& ray, TVector& t, Stats& stats) const = 0; - virtual bool point_is_on_surface(const Vector3 &p) const = 0; - virtual Vector3 compute_normal(const Vector3 &p) const = 0; + basics::Vector4 Normal(const basics::Vector4& p) const; + /** Write a string representation of this object to the stream. */ virtual void Write(std::ostream& ost) const; protected: + /** + * Do the actual intersection work. Subclasses are expected to override + * this. + */ virtual bool DoIntersect(const basics::Ray& ray, TVector& t, Stats& stats) const = 0; + /** + * Do the actual work of finding a normal for point p. Subclasses are + * expected to override this. + */ + virtual basics::Vector4 DoNormal(const basics::Vector4& p) const = 0; + private: + /** Convert `ray` to object space from global space. */ basics::Ray ToObjectSpace(const basics::Ray& ray) const; + /** Convert `v` to object space from global space. */ + basics::Vector4 ToObjectSpace(const basics::Vector4& v) const; + + /** Convert `v` to global space from object space. */ + basics::Vector4 FromObjectSpace(const basics::Vector4& v) const; + /** A translation matrix from global coordinates to this object's space. */ basics::Matrix4 mTranslation; @@ -72,13 +77,7 @@ private: }; -/** - * Write a string representation of the Object to an output stream. - * - * @param [in] ost The output stream - * @param [in] object The object - * @returns The output stream - */ +/** Write a string representation of the Object to an output stream. */ std::ostream& operator<<(std::ostream& ost, const Object& object); } /* namespace charles */ From 392871a1ee0f310a63434df2eab401736c3994af Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 10:54:00 -0700 Subject: [PATCH 35/92] Updates for Box --- src/objectBox.cc | 94 ++++++++++++++++++++++++++---------------------- src/objectBox.hh | 28 ++++++++------- 2 files changed, 66 insertions(+), 56 deletions(-) diff --git a/src/objectBox.cc b/src/objectBox.cc index f194a1a..90b5670 100644 --- a/src/objectBox.cc +++ b/src/objectBox.cc @@ -8,87 +8,95 @@ #include "objectBox.hh" +using charles::basics::Ray; +using charles::basics::Vector4; + + namespace charles { +/* + * charles::Box::Box -- + */ Box::Box() /* A unit box centered on the origin. */ - : Box(Vector3(-0.5, -0.5, -0.5), Vector3(0.5, 0.5, 0.5)) + : Box(Vector4(-0.5, -0.5, -0.5), Vector4(0.5, 0.5, 0.5)) { } -Box::Box(const Vector3& near, const Vector3& far) +/* + * charles::Box::Box -- + */ +Box::Box(const Vector4& near, + const Vector4& far) : Object(), mNear(near), mFar(far) { } -Vector3& +/* + * charles::Box::GetNear -- + */ +Vector4& Box::GetNear() { return mNear; } +/* + * charles::Box::SetNear -- + */ void -Box::SetNear(const Vector3& near) +Box::SetNear(const Vector4& near) { mNear = near; } -Vector3& +/* + * charles::Box::GetFar -- + */ +Vector4& Box::GetFar() { return mFar; } +/* + * charles::Box::SetFar -- + */ void -Box::SetFar(const Vector3& far) +Box::SetFar(const Vector4& far) { mFar = far; } -bool -Box::point_is_on_surface(const Vector3& p) +/* + * charles::Box::DoNormal -- + */ +Vector4 +Box::DoNormal(const Vector4& p) const { - if (p.x == mNear.x || p.x == mFar.x) { - return (p.y > mNear.y && p.y < mFar.y) - && (p.z > mNear.z && p.z < mFar.z); - } else if (p.y == mNear.y || p.y == mFar.y) { - return (p.x > mNear.x && p.x < mFar.x) - && (p.z > mNear.z && p.z < mFar.z); - } else if (p.z == mNear.z || p.z == mFar.z) { - return (p.x > mNear.x && p.x < mFar.x) - && (p.y > mNear.y && p.y < mFar.y); - } - return false; -} - - -Vector3 -Box::compute_normal(const Vector3& p) - const -{ - if (NearlyEqual(p.x, mNear.x)) { - return Vector3(-1, 0, 0); - } else if (NearlyEqual(p.x, mFar.x)) { - return Vector3(1, 0, 0); - } else if (NearlyEqual(p.y, mNear.y)) { - return Vector3(0, -1, 0); - } else if (NearlyEqual(p.y, mFar.y)) { - return Vector3(0, 1, 0); - } else if (NearlyEqual(p.z, mNear.z)) { - return Vector3(0, 0, -1); - } else if (NearlyEqual(p.z, mFar.z)) { - return Vector3(0, 0, 1); + if (NearlyEqual(p.X(), mNear.X())) { + return Vector4(-1, 0, 0); + } else if (NearlyEqual(p.X(), mFar.X())) { + return Vector4(1, 0, 0); + } else if (NearlyEqual(p.Y(), mNear.Y())) { + return Vector4(0, -1, 0); + } else if (NearlyEqual(p.Y(), mFar.Y())) { + return Vector4(0, 1, 0); + } else if (NearlyEqual(p.Z(), mNear.Z())) { + return Vector4(0, 0, -1); + } else if (NearlyEqual(p.Z(), mFar.Z())) { + return Vector4(0, 0, 1); } /* TODO: Eventually, I might want to raise an error here. */ - return Vector3(); + return Vector4(); } @@ -96,7 +104,7 @@ Box::compute_normal(const Vector3& p) * charles::Box::DoIntersect -- */ bool -Box::DoIntersect(const basics::Ray& ray, +Box::DoIntersect(const Ray& ray, TVector& t, Stats& stats) const @@ -108,17 +116,17 @@ Box::DoIntersect(const basics::Ray& ray, Double tNear = -std::numeric_limits::infinity(); Double tFar = std::numeric_limits::infinity(); - if (!IntersectSlab(mNear.x, mFar.x, + if (!IntersectSlab(mNear.X(), mFar.X(), ray.origin.X(), ray.direction.X(), tNear, tFar)) { return false; } - if (!IntersectSlab(mNear.y, mFar.y, + if (!IntersectSlab(mNear.Y(), mFar.Y(), ray.origin.Y(), ray.direction.Y(), tNear, tFar)) { return false; } - if (!IntersectSlab(mNear.z, mFar.z, + if (!IntersectSlab(mNear.Z(), mFar.Z(), ray.origin.Z(), ray.direction.Z(), tNear, tFar)) { return false; diff --git a/src/objectBox.hh b/src/objectBox.hh index 51a7281..55b3b7b 100644 --- a/src/objectBox.hh +++ b/src/objectBox.hh @@ -3,9 +3,11 @@ * Eryn Wells */ -#include "basics.h" -#include "object.h" -#include "types.hh" +#ifndef __OBJECTBOX_HH__ +#define __OBJECTBOX_HH__ + +#include "object.hh" +#include "basics/basics.hh" namespace charles { @@ -14,22 +16,20 @@ struct Box : public Object { Box(); - Box(const Vector3& near, const Vector3& far); + Box(const basics::Vector4& near, const basics::Vector4& far); - Vector3& GetNear(); - void SetNear(const Vector3& near); - Vector3& GetFar(); - void SetFar(const Vector3& far); + basics::Vector4& GetNear(); + void SetNear(const basics::Vector4& near); - bool DoesIntersect(const Ray& ray, TVector& t, Stats& stats) const; - bool point_is_on_surface(const Vector3 &p) const; - Vector3 compute_normal(const Vector3 &p) const; + basics::Vector4& GetFar(); + void SetFar(const basics::Vector4& far); /** @see charles::Object::Write */ void Write(std::ostream& ost) const; protected: bool DoIntersect(const basics::Ray& ray, TVector& t, Stats& stats) const; + basics::Vector4 DoNormal(const basics::Vector4& p) const; private: /** @@ -52,10 +52,12 @@ private: Double& tFar) const; /** The near, lower left corner. */ - Vector3 mNear; + basics::Vector4 mNear; /** The far, upper right corner. */ - Vector3 mFar; + basics::Vector4 mFar; }; } /* namespace charles */ + +#endif /* __OBJECTBOX_HH__ */ From 590f10a75692a81ebd1c4887122bb0bacc546a03 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 10:58:30 -0700 Subject: [PATCH 36/92] Updates for Plane --- src/objectPlane.cc | 65 +++++++++++++++++++++++----------------------- src/objectPlane.hh | 23 +++++++--------- 2 files changed, 42 insertions(+), 46 deletions(-) diff --git a/src/objectPlane.cc b/src/objectPlane.cc index d94a8e5..cbd3fd1 100644 --- a/src/objectPlane.cc +++ b/src/objectPlane.cc @@ -10,22 +10,28 @@ #include #include -#include "basics.h" -#include "object.h" #include "objectPlane.hh" + +using charles::basics::Ray; +using charles::basics::Vector4; + + namespace charles { /* * charles::Plane::Plane -- */ Plane::Plane() - : mNormal(Vector3::Y), + : mNormal(0, 1, 0), mDistance(0.0) { } -const Vector3& +/* + * charles::Plane::GetNormal -- + */ +const Vector4& Plane::GetNormal() const { @@ -33,13 +39,19 @@ Plane::GetNormal() } +/* + * charles::Plane::SetNormal -- + */ void -Plane::SetNormal(const Vector3& normal) +Plane::SetNormal(const Vector4& normal) { - mNormal = normal.normalized(); + mNormal = basics::Normalized(normal); } +/* + * charles::Plane::GetDistance -- + */ Double Plane::GetDistance() const @@ -48,6 +60,9 @@ Plane::GetDistance() } +/* + * charles::Plane::SetDistance -- + */ void Plane::SetDistance(Double distance) { @@ -59,9 +74,9 @@ Plane::SetDistance(Double distance) * charles::Plane::DoesIntersect -- */ bool -Plane::DoesIntersect(const Ray &ray, - TVector& t, - Stats& stats) +Plane::DoIntersect(const Ray& ray, + TVector& t, + Stats& stats) const { /* @@ -94,14 +109,14 @@ Plane::DoesIntersect(const Ray &ray, stats.planeIntersectionTests++; /* The denominator for the t equation above. */ - Double vd = mNormal.dot(ray.direction); + Double vd = mNormal.Dot(ray.direction); if (NearZero(vd)) { /* The ray is parallel to the plane. */ return false; } /* The numerator of the equation for t above. */ - Double vo = -(mNormal.dot(ray.origin) + mDistance); + Double vo = -(mNormal.Dot(ray.origin) + mDistance); Double t0 = vo / vd; if (t0 < 0.0) { @@ -119,33 +134,14 @@ Plane::DoesIntersect(const Ray &ray, } -/* - * charles::Plane::point_is_on_surface -- - */ -bool -Plane::point_is_on_surface(const Vector3 &p) - const -{ - /* - * Plug point p into the equation for a plane: - * - * A * x + B * y + C * z + D = 0 - * - * where (A, B, C) are the coordinates of the normal vector, and D is the - * distance along that vector from the origin. - */ - return NearZero(mNormal.dot(p) + mDistance); -} - - #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-parameter" /* - * charles::Plane::compute_normal -- + * charles::Plane::DoNormal -- */ -Vector3 -Plane::compute_normal(const Vector3 &p) +Vector4 +Plane::DoNormal(const Vector4& p) const { return mNormal; @@ -154,6 +150,9 @@ Plane::compute_normal(const Vector3 &p) #pragma clang diagnostic pop +/* + * charles::Plane::Write -- + */ void Plane::Write(std::ostream& ost) const diff --git a/src/objectPlane.hh b/src/objectPlane.hh index 9dabbb4..38c6207 100644 --- a/src/objectPlane.hh +++ b/src/objectPlane.hh @@ -8,9 +8,9 @@ #ifndef __OBJECT_PLANE_H__ #define __OBJECT_PLANE_H__ -#include "basics.h" -#include "object.h" -#include "types.hh" +#include "object.hh" +#include "basics/basics.hh" + namespace charles { @@ -21,25 +21,22 @@ public: /** Default constructor. Creates a plane with a normal along the Y axis. */ Plane(); - const Vector3& GetNormal() const; - void SetNormal(const Vector3& normal); + const basics::Vector4& GetNormal() const; + void SetNormal(const basics::Vector4& normal); Double GetDistance() const; void SetDistance(Double distance); - /** - * @see charles::Object::DoesIntersect - */ - bool DoesIntersect(const Ray &ray, TVector& t, Stats& stats) const; - bool point_is_on_surface(const Vector3 &p) const; - Vector3 compute_normal(const Vector3 &p) const; - /** @see charles::Object::Write */ void Write(std::ostream& ost) const; +protected: + bool DoIntersect(const basics::Ray& ray, TVector& t, Stats& stats) const; + basics::Vector4 DoNormal(const basics::Vector4& p) const; + private: /** A normal vector, which specified the orientation of the plane. */ - Vector3 mNormal; + basics::Vector4 mNormal; /** * The distance from the origin along the normal vector that this plane is From 19dfb66301a6ea5ddd6e69c654980efc45d9a728 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 11:04:17 -0700 Subject: [PATCH 37/92] Cleanup for Spheres --- src/objectSphere.cc | 70 ++++++++++++++++++--------------------------- src/objectSphere.hh | 13 ++++----- 2 files changed, 34 insertions(+), 49 deletions(-) diff --git a/src/objectSphere.cc b/src/objectSphere.cc index d0ea008..a6229df 100644 --- a/src/objectSphere.cc +++ b/src/objectSphere.cc @@ -1,7 +1,5 @@ -/* object_sphere.h - * - * Spheres are Scene objects defined by a center point and a radius. - * +/* objectSphere.cc + * vim: set tw=80: * Eryn Wells */ @@ -10,11 +8,10 @@ #include #include -#include "basics.h" -#include "object.h" #include "objectSphere.hh" +using charles::basics::Ray; using charles::basics::Vector4; @@ -30,6 +27,9 @@ Sphere::Sphere(const Vector4& origin, { } +/* + * charles::Sphere::GetRadius -- + */ Double Sphere::GetRadius() const @@ -38,28 +38,31 @@ Sphere::GetRadius() } +/* + * charles::Sphere::SetRadius -- + */ void -Sphere::SetRadius(Double r) +Sphere::SetRadius(const Double& r) { mRadius = std::fabs(r); } /* - * Sphere::DoesIntersect -- + * charles::Sphere::DoesIntersect -- */ bool -Sphere::DoesIntersect(const Ray& ray, - TVector& t, - Stats& stats) +Sphere::DoIntersect(const Ray& ray, + TVector& t, + Stats& stats) const { stats.sphereIntersectionTests++; /* Coefficients for quadratic equation. */ - Double a = ray.direction.dot(ray.direction); - Double b = ray.direction.dot(ray.origin) * 2.0; - Double c = ray.origin.dot(ray.origin) - (mRadius * mRadius); + Double a = ray.direction.Dot(ray.direction); + Double b = ray.direction.Dot(ray.origin) * 2.0; + Double c = ray.origin.Dot(ray.origin) - (mRadius * mRadius); /* Discriminant for the quadratic equation. */ Double discrim = (b * b) - (4.0 * a * c); @@ -76,7 +79,7 @@ Sphere::DoesIntersect(const Ray& ray, * Compute the intersections, the roots of the quadratic equation. Spheres * have at most two intersections. */ - Double sqrtDiscrim = sqrt(discrim); + Double sqrtDiscrim = std::sqrt(discrim); Double t0 = (-b - sqrtDiscrim) / (2.0 * a); Double t1 = (-b + sqrtDiscrim) / (2.0 * a); @@ -109,45 +112,28 @@ Sphere::DoesIntersect(const Ray& ray, /* - * Sphere::point_is_on_surface -- - * - * Determine if a point lies on the surface of this Sphere. + * charles::Sphere::DoNormal -- */ -bool -Sphere::point_is_on_surface(const Vector3 &p) +Vector4 +Sphere::DoNormal(const Vector4& p) const { - Vector3 o = GetOrigin(); - Double x = p.x - o.x; - Double y = p.y - o.y; - Double z = p.z - o.z; - - return x*x + y*y + z*z == mRadius*mRadius; + /* + * The fun thing about sphere is the normal to any point on the sphere is + * the point itself. Woo! + */ + return Normalized(p); } /* - * Sphere::compute_normal -- - * - * Compute the normal for this Sphere at the given point. If the point does not lie on the surface of the sphere, a zero - * vector is returned. + * charles::Sphere::Write -- */ -Vector3 -Sphere::compute_normal(const Vector3 &p) - const -{ - // The fun thing about sphere is the normal to any point on the sphere is the point itself. Woo! - Vector3 normal = p - GetOrigin(); - normal.normalize(); - return normal; -} - - void Sphere::Write(std::ostream& ost) const { - ost << "[Sphere origin=" << GetOrigin() << " r=" << mRadius << "]"; + ost << "[Sphere r=" << mRadius << "]"; } } /* namespace charles */ diff --git a/src/objectSphere.hh b/src/objectSphere.hh index 9597868..7ad62d1 100644 --- a/src/objectSphere.hh +++ b/src/objectSphere.hh @@ -8,8 +8,7 @@ #ifndef __OBJECTSPHERE_HH__ #define __OBJECTSPHERE_HH__ -#include "basics.h" -#include "object.h" +#include "object.hh" #include "basics/basics.hh" @@ -22,15 +21,15 @@ public: Sphere(const basics::Vector4& origin = basics::Vector4(), Double radius = 1.0); Double GetRadius() const; - void SetRadius(Double r); - - bool DoesIntersect(const Ray& ray, TVector& t, Stats& stats) const; - bool point_is_on_surface(const Vector3 &p) const; - Vector3 compute_normal(const Vector3 &p) const; + void SetRadius(const Double& r); /** @see charles::Object::Write */ void Write(std::ostream& ost) const; +protected: + bool DoIntersect(const basics::Ray& ray, TVector& t, Stats& stats) const; + basics::Vector4 DoNormal(const basics::Vector4& p) const; + private: Double mRadius; }; From d10d219eb394706e25757b008da74b6cf417f44c Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 11:04:26 -0700 Subject: [PATCH 38/92] Comment out old Ray --- src/basics.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/basics.h b/src/basics.h index d703514..e63d299 100644 --- a/src/basics.h +++ b/src/basics.h @@ -195,6 +195,7 @@ Matrix4 operator*(const Double lhs, const Matrix4& rhs); #endif +#if 0 struct Ray { Ray(); @@ -206,6 +207,7 @@ struct Ray }; std::ostream &operator<<(std::ostream &os, const Ray &r); +#endif struct Color From 9645a09a6cecc48360c9a434f170ec4472a667c9 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 11:26:17 -0700 Subject: [PATCH 39/92] So much clean up for cameras --- src/camera.cc | 177 ++++++++++++++++++++++++++++++++++++-------------- src/camera.h | 117 --------------------------------- src/camera.hh | 125 +++++++++++++++++++++++++++++++++++ 3 files changed, 255 insertions(+), 164 deletions(-) delete mode 100644 src/camera.h create mode 100644 src/camera.hh diff --git a/src/camera.cc b/src/camera.cc index 4605497..86ed8be 100644 --- a/src/camera.cc +++ b/src/camera.cc @@ -3,29 +3,45 @@ * Eryn Wells */ -#include "camera.h" +#include "camera.hh" #include "log.hh" #define LOG_NAME "camera" #include "logModule.hh" +using charles::basics::Ray; +using charles::basics::Vector4; + + +namespace charles { + #pragma mark - Generic Camera +/* + * charles::Camera::Camera -- + */ Camera::Camera() - : mDirection(Vector3::Z), + : mDirection(0, 0, 1), mRight(1.33, 0, 0), - mUp(Vector3::Y) + mUp(0, 1, 0) { } -Camera::Camera(const Camera& other) - : mDirection(other.mDirection), - mRight(other.mRight), - mUp(other.mUp) +/* + * charles::Camera::Camera -- + */ +Camera::Camera(const Camera& rhs) + : mOrigin(rhs.mOrigin), + mDirection(rhs.mDirection), + mRight(rhs.mRight), + mUp(rhs.mUp) { } +/* + * charles::Camera::~Camera -- + */ Camera::~Camera() { } @@ -33,7 +49,17 @@ Camera::~Camera() /* * Camera::GetOrigin -- */ -const Vector3& +Vector4& +Camera::GetOrigin() +{ + return mOrigin; +} + + +/* + * Camera::GetOrigin -- + */ +const Vector4& Camera::GetOrigin() const { @@ -45,27 +71,57 @@ Camera::GetOrigin() * Camera::SetOrigin -- */ void -Camera::SetOrigin(const Vector3 &origin) +Camera::SetOrigin(const Vector4& origin) { mOrigin = origin; } -const Vector3& -Camera::get_direction() +/* + * Camera::GetDirection -- + */ +Vector4& +Camera::GetDirection() +{ + return mDirection; +} + + +/* + * Camera::GetDirection -- + */ +const Vector4& +Camera::GetDirection() const { return mDirection; } + +/* + * Camera::SetDirection -- + */ void -Camera::set_direction(const Vector3 &direction) +Camera::SetDirection(const Vector4& direction) { mDirection = direction; } -const Vector3& +/* + * Camera::GetRight -- + */ +Vector4& +Camera::GetRight() +{ + return mRight; +} + + +/* + * Camera::GetRight -- + */ +const Vector4& Camera::GetRight() const { @@ -73,14 +129,30 @@ Camera::GetRight() } +/* + * Camera::SetRight -- + */ void -Camera::SetRight(const Vector3& right) +Camera::SetRight(const Vector4& right) { mRight = right; } -const Vector3& +/* + * Camera::GetUp -- + */ +Vector4& +Camera::GetUp() +{ + return mUp; +} + + +/* + * Camera::GetUp -- + */ +const Vector4& Camera::GetUp() const { @@ -88,13 +160,19 @@ Camera::GetUp() } +/* + * Camera::SetUp -- + */ void -Camera::SetUp(const Vector3& up) +Camera::SetUp(const Vector4& up) { mUp = up; } +/* + * Camera::IsLeftHanded -- + */ bool Camera::IsLeftHanded() const @@ -110,24 +188,27 @@ Camera::IsLeftHanded() * than 0, the vector is pointing left of the up-direction plane and the * coordinate system is left-handed. */ - return mUp.cross(mDirection).dot(mRight) < 0.0; + return mUp.Cross(mDirection).Dot(mRight) < 0.0; } +/* + * Camera::LookAt -- + */ void -Camera::LookAt(const Vector3& pt) +Camera::LookAt(const Vector4& p) { /* * Precalulate these in order to preserve the aspect ratio and orientation * of the camera across the LookAt operation. */ - const Double directionLength = mDirection.length(); - const Double rightLength = mRight.length(); - const Double upLength = mUp.length(); + const Double directionLength = mDirection.Length(); + const Double rightLength = mRight.Length(); + const Double upLength = mUp.Length(); const bool isLeftHanded = IsLeftHanded(); /* Orient the camera towards the point. */ - mDirection = (pt - mOrigin).normalize(); + mDirection = basics::Normalized(p - mOrigin); /* TODO: Check for zero length direction vector. */ /* @@ -141,8 +222,8 @@ Camera::LookAt(const Vector3& pt) * specifies the vector along which LookAt pans and tilts the camera. It * might be worth looking into, at some point. */ - mRight = Vector3::Y.cross(mDirection).normalize(); - mUp = mDirection.cross(mRight); + mRight = basics::Normalized(Vector4(0, 1, 0).Cross(mDirection)); + mUp = mDirection.Cross(mRight); /* * Now, fix up the direction, right, and up vectors so that their magnitudes @@ -152,10 +233,13 @@ Camera::LookAt(const Vector3& pt) mRight *= isLeftHanded ? rightLength : -rightLength; mUp *= upLength; - LOG_DEBUG << "Camera is looking at " << pt; + LOG_DEBUG << "Camera is looking at " << p; } +/* + * charles::Camera::GetTypeString -- + */ std::string Camera::GetTypeString() const @@ -164,6 +248,9 @@ Camera::GetTypeString() } +/* + * charles::Camera::WriteType -- + */ void Camera::WriteType(std::ostream& ost) const @@ -184,23 +271,23 @@ PerspectiveCamera::PerspectiveCamera(const Camera& other) Ray -PerspectiveCamera::compute_primary_ray(const int x, - const int width, - const int y, - const int height) +PerspectiveCamera::PrimaryRay(const int x, + const int width, + const int y, + const int height) const { /* * Center x and y in the pixel and convert them to be coordinates between * -0.5 and 0.5. */ - double x0 = (x + 0.5) / width - 0.5; - double y0 = ((height - 1.0) - (y - 0.5)) / height - 0.5; + Double x0 = (x + 0.5) / width - 0.5; + Double y0 = ((height - 1.0) - (y - 0.5)) / height - 0.5; - Vector3 direction = LinearCombination(1.0, get_direction(), + Vector4 direction = LinearCombination(1.0, GetDirection(), x0, GetRight(), y0, GetUp()); - return Ray(GetOrigin(), direction.normalize()); + return Ray(GetOrigin(), basics::Normalized(direction)); } @@ -226,30 +313,24 @@ OrthographicCamera::OrthographicCamera(const Camera& other) /* * OrthographicCamera::compute_primary_ray -- */ -/** - * Compute a primary ray given an (x,y) coordinate pair. The orthographic camera - * projects rays parallel to the viewing direction through the (x,y) coordinate - * given. Thus, the size of the orthographic camera should be set to the size of - * the view into the scene. - */ Ray -OrthographicCamera::compute_primary_ray(const int x, - const int width, - const int y, - const int height) +OrthographicCamera::PrimaryRay(const int x, + const int width, + const int y, + const int height) const { /* * Center x and y in the pixel and convert them to be coordinates between * -0.5 and 0.5. */ - double x0 = (x + 0.5) / width + 0.5; - double y0 = ((height - 1.0) - (y - 0.5)) / height - 0.5; + Double x0 = (x + 0.5) / width + 0.5; + Double y0 = ((height - 1.0) - (y - 0.5)) / height - 0.5; - Vector3 origin = LinearCombination(1.0, GetOrigin(), + Vector4 origin = LinearCombination(1.0, GetOrigin(), x0, GetRight(), y0, GetUp()); - return Ray(origin, get_direction()); + return Ray(origin, GetDirection()); } @@ -274,3 +355,5 @@ operator<<(std::ostream& ost, << "]"; return ost; } + +} /* namespace charles */ diff --git a/src/camera.h b/src/camera.h deleted file mode 100644 index f3b46d1..0000000 --- a/src/camera.h +++ /dev/null @@ -1,117 +0,0 @@ -/* camera.h - * - * The Camera is the eye into the scene. It defines several parameters and a - * single compute_primary_ray method that generates rays with which the ray - * tracer draws the scene. - * - * Eryn Wells - */ - -#ifndef __CAMERA_H__ -#define __CAMERA_H__ - -#include - -#include "basics.h" - - -struct Camera -{ - typedef std::shared_ptr Ptr; - - Camera(); - Camera(const Camera& other); - virtual ~Camera(); - - const Vector3& GetOrigin() const; - void SetOrigin(const Vector3& origin); - - const Vector3& get_direction() const; - void set_direction(const Vector3& direction); - - const Vector3& GetRight() const; - void SetRight(const Vector3& right); - - const Vector3& GetUp() const; - void SetUp(const Vector3& up); - - /** - * Get the camera's handedness. Left handed is the default. - * - * @returns `true` if the camera is set up for left-handed coordinates. - */ - bool IsLeftHanded() const; - - /** - * Pan and tilt the camera towards the given point. - * - * @param [in] pt The point at which to face the camera - */ - void LookAt(const Vector3& pt); - - virtual Ray compute_primary_ray(const int x, const int width, - const int y, const int height) const = 0; - - virtual std::string GetTypeString() const; - -private: - friend std::ostream& operator<<(std::ostream& ost, const Camera& camera); - - void WriteType(std::ostream& ost) const; - - /** - * The location of the camera in the scene. Depending on the type of camera, - * this is the point from which rays will be emitted. - */ - Vector3 mOrigin; - - /** A normalized vector defining where the camera is pointed. */ - Vector3 mDirection; - - /** - * A vector defining the width of the camera's image plane. The ratio of - * this and mUp determine the aspect ratio of the image. - */ - Vector3 mRight; - - /** - * A vector defining the height of the camera's image plane. The ratio of - * this and mRight determine the aspect ratio of the image. - */ - Vector3 mUp; -}; - - -class PerspectiveCamera - : public Camera -{ -public: - PerspectiveCamera(); - PerspectiveCamera(const Camera& other); - - Ray compute_primary_ray(const int x, const int width, - const int y, const int height) const; - -private: - std::string GetTypeString() const; -}; - - -class OrthographicCamera - : public Camera -{ -public: - OrthographicCamera(); - OrthographicCamera(const Camera& other); - - Ray compute_primary_ray(const int x, const int width, - const int y, const int height) const; - -private: - std::string GetTypeString() const; -}; - - -std::ostream& operator<<(std::ostream& ost, const Camera& camera); - -#endif diff --git a/src/camera.hh b/src/camera.hh new file mode 100644 index 0000000..2b006da --- /dev/null +++ b/src/camera.hh @@ -0,0 +1,125 @@ +/* camera.hh + * vim: set tw=80: + * Eryn Wells + */ + +#ifndef __CAMERA_H__ +#define __CAMERA_H__ + +#include + +#include "basics/basics.hh" + + +namespace charles { + +/** + * The Camera is the eye into the scene. It defines several parameters and a + * single compute_primary_ray method that generates rays with which the ray + * tracer draws the scene. + */ +struct Camera +{ + typedef std::shared_ptr Ptr; + + Camera(); + Camera(const Camera& other); + virtual ~Camera(); + + basics::Vector4& GetOrigin(); + const basics::Vector4& GetOrigin() const; + void SetOrigin(const basics::Vector4& origin); + + basics::Vector4& GetDirection(); + const basics::Vector4& GetDirection() const; + void SetDirection(const basics::Vector4& direction); + + basics::Vector4& GetRight(); + const basics::Vector4& GetRight() const; + void SetRight(const basics::Vector4& right); + + basics::Vector4& GetUp(); + const basics::Vector4& GetUp() const; + void SetUp(const basics::Vector4& up); + + /** Get the camera's handedness. Left handed is the default. */ + bool IsLeftHanded() const; + + /** Pan and tilt the camera towards the given point. */ + void LookAt(const basics::Vector4& p); + + virtual basics::Ray PrimaryRay(const int x, const int width, + const int y, const int height) const = 0; + +protected: + virtual std::string GetTypeString() const; + +private: + friend std::ostream& operator<<(std::ostream& ost, const Camera& camera); + + void WriteType(std::ostream& ost) const; + + /** + * The location of the camera in the scene. Depending on the type of camera, + * this is the point from which rays will be emitted. + */ + basics::Vector4 mOrigin; + + /** A vector defining where the camera is pointed. */ + basics::Vector4 mDirection; + + /** + * A vector defining the width of the camera's image plane. The ratio of + * this and mUp determine the aspect ratio of the image. + */ + basics::Vector4 mRight; + + /** + * A vector defining the height of the camera's image plane. The ratio of + * this and mRight determine the aspect ratio of the image. + */ + basics::Vector4 mUp; +}; + + +class PerspectiveCamera + : public Camera +{ +public: + PerspectiveCamera(); + PerspectiveCamera(const Camera& other); + + basics::Ray PrimaryRay(const int x, const int width, + const int y, const int height) const; + +private: + std::string GetTypeString() const; +}; + + +class OrthographicCamera + : public Camera +{ +public: + OrthographicCamera(); + OrthographicCamera(const Camera& other); + + /** + * Compute a primary ray given an (x,y) coordinate pair. The orthographic + * camera projects rays parallel to the viewing direction through the (x,y) + * coordinate given. Thus, the size of the orthographic camera should be set + * to the size of the view into the scene. + */ + basics::Ray PrimaryRay(const int x, const int width, + const int y, const int height) const; + +private: + std::string GetTypeString() const; +}; + + +std::ostream& operator<<(std::ostream& ost, const Camera& camera); + +} /* namespace charles */ + +#endif From c49457a817d3f7d1301f56c4ccda28d610cc607d Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 11:55:10 -0700 Subject: [PATCH 40/92] Implement Normalized, LinearCombination, and operator<< on Vector4s --- src/basics/vector.cc | 36 ++++++++++++++++++++++++++++++++++++ src/basics/vector.hh | 12 +++++++++++- 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/basics/vector.cc b/src/basics/vector.cc index a2d65f8..af09696 100644 --- a/src/basics/vector.cc +++ b/src/basics/vector.cc @@ -224,6 +224,42 @@ operator*(const Double& lhs, return rhs * lhs; } + +/* + * charles::basics::Normalized -- + */ +Vector4 +Normalized(const Vector4& v) +{ + return Vector4(v).Normalize(); +} + + +/* + * charles::basics::LinearCombination -- + */ +Vector4 +LinearCombination(const Double k1, const Vector4& v1, + const Double k2, const Vector4& v2, + const Double k3, const Vector4& v3) +{ + return Vector4(k1 * v1.X() + k2 * v2.X() + k3 * v3.X(), + k1 * v1.Y() + k2 * v2.Y() + k3 * v3.Y(), + k1 * v1.Z() + k2 * v2.Z() + k3 * v3.Z()); +} + + +/* + * charles::basics::operator<< -- + */ +std::ostream & +operator<<(std::ostream &os, const Vector3 &v) +{ + // Stream the vector like this: + os << "<" << v.X() << ", " << v.Y() << ", " << v.Z() << ">"; + return os; +} + } /* namespace basics */ } /* namespace charles */ diff --git a/src/basics/vector.hh b/src/basics/vector.hh index 4069d87..e5ce24c 100644 --- a/src/basics/vector.hh +++ b/src/basics/vector.hh @@ -6,6 +6,8 @@ #ifndef __BASICS_VECTOR_HH__ #define __BASICS_VECTOR_HH__ +#include + #include "basics/matrix.hh" #include "basics/types.hh" @@ -63,7 +65,15 @@ Vector4 operator*(const Double& lhs, const Vector4& rhs); /** Normalize the given vector and return a copy of it. */ -Vector4& Normalized(const Vector4& v); +Vector4 Normalized(const Vector4& v); + + +Vector4 LinearCombination(const Double k1, const Vector4& v1, + const Double k2, const Vector4& v2, + const Double k3, const Vector4& v3); + + +std::ostream& operator<<(std::ostream& ost, const Vector4& v); } /* namespace basics */ } /* namespace charles */ From 47ae52ed051e6c438cfd952e1cb368ca96fd19c6 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 12:25:59 -0700 Subject: [PATCH 41/92] Woo Scene updates... --- src/camera.hh | 1 - src/scene.cc | 311 ++++++++++++++++++++++++++++---------------------- src/scene.h | 84 -------------- src/scene.hh | 86 ++++++++++++++ 4 files changed, 258 insertions(+), 224 deletions(-) delete mode 100644 src/scene.h create mode 100644 src/scene.hh diff --git a/src/camera.hh b/src/camera.hh index 2b006da..b34e605 100644 --- a/src/camera.hh +++ b/src/camera.hh @@ -51,7 +51,6 @@ struct Camera virtual basics::Ray PrimaryRay(const int x, const int width, const int y, const int height) const = 0; -protected: virtual std::string GetTypeString() const; private: diff --git a/src/scene.cc b/src/scene.cc index 9aae326..d64a05a 100644 --- a/src/scene.cc +++ b/src/scene.cc @@ -5,84 +5,123 @@ * Eryn Wells */ -#include +#include #include #include +#include + +#include "scene.hh" #include "basics.h" #include "light.h" #include "log.hh" -#include "object.h" -#include "scene.h" +#include "object.hh" #include "writer.h" +#include "basics/basics.hh" #define LOG_NAME "scene" #include "logModule.hh" -using namespace charles; + +using charles::basics::Ray; +using charles::basics::Vector4; +namespace charles { + +/* + * charles::Scene::Scene -- + */ Scene::Scene() - : width(640), height(480), + : mWidth(640), + mHeight(480), mCamera(new PerspectiveCamera()), - max_depth(5), - min_weight(1e-4), - ambient(new AmbientLight()), - shapes(), - lights(), + mMaxDepth(5), + mMinWeight(1e-6), + mAmbient(), + mObjects(), + mLights(), mStats(), - pixels(NULL) + mPixels(NULL) { } +/* + * charles::Scene::~Scene -- + */ Scene::~Scene() { mCamera.reset(); - if (ambient != NULL) { - delete ambient; - } + mObjects.clear(); - shapes.clear(); - - for (PointLight *l : lights) { + for (PointLight *l : mLights) { delete l; } - lights.clear(); + mLights.clear(); - if (pixels != NULL) { - delete[] pixels; - _is_rendered = false; + if (mPixels != NULL) { + delete[] mPixels; + mIsRendered = false; } } -bool -Scene::is_rendered() - const -{ - return _is_rendered; -} - - -int -Scene::get_width() - const -{ - return width; -} - - -int -Scene::get_height() - const -{ - return height; -} - - /* - * Scene::GetCamera -- + * charles::Scene::IsRendered -- + */ +bool +Scene::IsRendered() + const +{ + return mIsRendered; +} + + +/* + * charles::Scene::GetWidth -- + */ +UInt +Scene::GetWidth() + const +{ + return mWidth; +} + + +/* + * charles::Scene::SetWidth -- + */ +void +Scene::SetWidth(UInt w) +{ + mWidth = w; +} + + +/* + * charles::Scene::GetHeight -- + */ +UInt +Scene::GetHeight() + const +{ + return mHeight; +} + + +/* + * charles::Scene::SetHeight -- + */ +void +Scene::SetHeight(UInt h) +{ + mHeight = h; +} + + +/* + * charles::Scene::GetCamera -- */ Camera::Ptr Scene::GetCamera() @@ -93,63 +132,55 @@ Scene::GetCamera() /* - * Scene::SetCamera -- + * charles::Scene::SetCamera -- */ void -Scene::SetCamera(Camera* camera) +Scene::SetCamera(Camera::Ptr camera) { - mCamera.reset(camera); -} - - -AmbientLight & -Scene::get_ambient() - const -{ - return *ambient; -} - - -const Color * -Scene::get_pixels() - const -{ - return pixels; + mCamera = camera; } /* - * scene_load -- - * - * Load scene objects into this Scene from the given file. + * charles::Scene::GetAmbient -- */ -void -Scene::read(const std::string &filename) -{ } +AmbientLight& +Scene::GetAmbient() +{ + return mAmbient; +} /* - * scene_save -- - * - * Write a rendered scene to the given file. + * charles::Scene::GetPixels -- + */ +const Color* +Scene::GetPixels() + const +{ + return mPixels; +} + + +/* + * charles::Scene::Write -- */ void -Scene::write(Writer &writer, const std::string &filename) +Scene::Write(Writer& writer, + const std::string& filename) { writer.write_scene(*this, filename); } /* - * Scene::render -- - * - * Render the given Scene. + * charles::Scene::Render -- */ void -Scene::render() +Scene::Render() { - LOG_INFO << "Rendering scene with " << shapes.size() << " objects."; - printf("Rendering scene with %lu objects.\n", shapes.size()); + LOG_INFO << "Rendering scene with " << mObjects.size() << " objects."; + printf("Rendering scene with %lu objects.\n", mObjects.size()); LogCamera(); LogObjects(); @@ -157,23 +188,23 @@ Scene::render() std::chrono::time_point start, end; start = std::chrono::system_clock::now(); - pixels = new Color[width * height]; + mPixels = new Color[mWidth * mHeight]; - Ray primary_ray; - Vector3 o, d; - for (int y = 0; y < height; y++) { - for (int x = 0; x < width; x++) { - primary_ray = mCamera->compute_primary_ray(x, width, y, height); + Ray primaryRay; + Vector4 o, d; + for (UInt y = 0; y < mHeight; y++) { + for (UInt x = 0; x < mWidth; x++) { + primaryRay = mCamera->PrimaryRay(x, mWidth, y, mHeight); mStats.primaryRays++; - Color c = trace_ray(primary_ray); - pixels[y * width + x] = c; + Color c = TraceRay(primaryRay); + mPixels[y * mWidth + x] = c; } } end = std::chrono::system_clock::now(); - std::chrono::duration seconds = end - start; + std::chrono::duration seconds = end - start; - _is_rendered = true; + mIsRendered = true; printf("Rendering completed in %f seconds.\n\n", seconds.count()); LOG_INFO << "Rendering completed in " << seconds.count() << " seconds."; @@ -184,83 +215,77 @@ Scene::render() /* - * Scene::add_shape -- - * - * Add a shape to the scene. + * charles::Scene::AddObject -- */ void -Scene::add_shape(Object::Ptr shape) +Scene::AddObject(Object::Ptr obj) { - shapes.push_back(shape); + mObjects.push_back(obj); } /* - * Scene::add_light -- - * - * Add a light to the scene. + * charles::Scene::AddLight -- */ void -Scene::add_light(PointLight *light) +Scene::AddLight(PointLight* light) { - lights.push_back(light); + mLights.push_back(light); } /* - * Scene::trace_ray -- - * - * Trace the given ray through the scene, recursing until depth has been reached. + * charles::Scene::TraceRay -- */ Color -Scene::trace_ray(const Ray &ray, - const int depth, - const float weight) +Scene::TraceRay(const Ray &ray, + const int depth, + const Double weight) { - if (depth >= max_depth || weight <= min_weight) { + if (depth >= mMaxDepth || weight <= mMinWeight) { return Color::Black; } - Color out_color = Color::Black; - Object::Ptr intersected_shape; + Color outColor = Color::Black; + Object::Ptr intersectedObj; TVector ts; - Double nearest_t = INFINITY; + Double nearestT = INFINITY; ts.reserve(2); // Find intersections of this ray with objects in the scene. - for (Object::Ptr s : shapes) { + for (Object::Ptr obj : mObjects) { ts.clear(); - if (s->DoesIntersect(ray, ts, mStats)) { - if (ts[0] < nearest_t) { - intersected_shape = s; - nearest_t = ts[0]; + if (obj->Intersect(ray, ts, mStats)) { + if (ts[0] < nearestT) { + intersectedObj = obj; + nearestT = ts[0]; } } } // If there was no intersection, return black. - if (!intersected_shape) { - return out_color; + if (!intersectedObj) { + return outColor; } - Material& shape_material = intersected_shape->GetMaterial(); - const Color& shape_color = shape_material.GetDiffuseColor(); + Material& material = intersectedObj->GetMaterial(); + const Color& shapeColor = material.GetDiffuseColor(); - Vector3 intersection = ray.parameterize(nearest_t); - Vector3 normal = intersected_shape->compute_normal(intersection); + Vector4 intersection = ray.Parameterize(nearestT); + Vector4 normal = intersectedObj->Normal(intersection); /* * Diffuse lighting. (Shading, etc.) */ - Vector3 light_direction; - Double ldotn, diffuse_level, ambient_level; + Vector4 lightDirection; + Double ldotn, diffuseLevel, ambientLevel; Ray shadowRay; - for (PointLight *l : lights) { - light_direction = (l->GetOrigin() - intersection).normalize(); - ldotn = light_direction.dot(normal); + for (PointLight *l : mLights) { + lightDirection = (l->GetOrigin() - intersection).normalize(); + ldotn = lightDirection.Dot(normal); /* * TODO: What is this even for? Removing it makes the darker showers @@ -270,12 +295,12 @@ Scene::trace_ray(const Ray &ray, ldotn = 0.0; } - diffuse_level = shape_material.GetDiffuseIntensity(); - ambient_level = 1.0 - diffuse_level; + diffuseLevel = material.GetDiffuseIntensity(); + ambientLevel = 1.0 - diffuseLevel; - shadowRay = Ray(intersection, light_direction); - for (Object::Ptr s : shapes) { - if (s == intersected_shape) { + shadowRay = Ray(intersection, lightDirection); + for (Object::Ptr obj : mObjects) { + if (obj == intersectedObj) { /* Skip the intersected shape. */ continue; } @@ -284,8 +309,8 @@ Scene::trace_ray(const Ray &ray, /* Figure out if we're in shadow. */ ts.clear(); - if (s->DoesIntersect(shadowRay, ts, mStats)) { - diffuse_level = 0.0; + if (obj->Intersect(shadowRay, ts, mStats)) { + diffuseLevel = 0.0; break; } } @@ -293,8 +318,8 @@ Scene::trace_ray(const Ray &ray, /* * Compute basic Lambert diffuse shading for this object. */ - out_color += shape_color * ( ambient_level * ambient->compute_color_contribution() - + diffuse_level * ldotn); + outColor += shapeColor * ( ambientLevel * mAmbient.compute_color_contribution() + + diffuseLevel * ldotn); } /* @@ -328,10 +353,13 @@ Scene::trace_ray(const Ray &ray, out_color += specular_level * specular_color * reflection_color; #endif - return out_color; + return outColor; } +/* + * charles::Scene::LogCamera -- + */ void Scene::LogCamera() const @@ -341,7 +369,7 @@ Scene::LogCamera() LOG_DEBUG << "BEGIN CAMERA"; LOG_DEBUG << " type = " << c.GetTypeString(); LOG_DEBUG << " origin = " << c.GetOrigin(); - LOG_DEBUG << " direction = " << c.get_direction(); + LOG_DEBUG << " direction = " << c.GetDirection(); LOG_DEBUG << " right = " << c.GetRight(); LOG_DEBUG << " up = " << c.GetUp(); LOG_DEBUG << " coordinate system is " @@ -350,15 +378,20 @@ Scene::LogCamera() } +/* + * charles::Scene::LogObjects -- + */ void Scene::LogObjects() const { LOG_DEBUG << "BEGIN SCENE OBJECTS"; - for (Object::Ptr obj : shapes) { + for (Object::Ptr obj : mObjects) { LOG_DEBUG << " " << *obj; } LOG_DEBUG << "END SCENE OBJECTS"; } + +} /* namespace charles */ diff --git a/src/scene.h b/src/scene.h deleted file mode 100644 index d8a86ad..0000000 --- a/src/scene.h +++ /dev/null @@ -1,84 +0,0 @@ -/* scene.h - * - * Definition of the Scene class. - * - * Scenes are the top level object in charles. Scenes contain objects, lights, a camera, - * etc. and can be rendered to pixel data and written to a file. - * - * Eryn Wells - */ - -#ifndef __SCENE_H__ -#define __SCENE_H__ - -#include -#include -#include "basics.h" -#include "camera.h" -#include "object.h" -#include "stats.hh" - - -class AmbientLight; -class PointLight; -class Writer; - - -class Scene -{ -public: - Scene(); - ~Scene(); - - bool is_rendered() const; - - int get_width() const; - void set_width(int w) { width = w; } - int get_height() const; - void set_height(int h) { height = h; } - - Camera::Ptr GetCamera() const; - void SetCamera(Camera* camera); - - AmbientLight &get_ambient() const; - const Color *get_pixels() const; - - void read(const std::string &filename); - void write(Writer &writer, const std::string &filename); - void render(); - - void add_shape(charles::Object::Ptr obj); - void add_light(PointLight *light); - -private: - Color trace_ray(const Ray &ray, const int depth = 0, const float weight = 1.0); - - void LogCamera() const; - void LogObjects() const; - - // Pixel dimensions of the image. - int width, height; - - Camera::Ptr mCamera; - - /* - * Ray tracing parameters. max_depth indicates the maximum depth of the ray tree. min_weight indicates the minimum - * specular weight to apply before giving up. - */ - int max_depth; - float min_weight; - - // Scene objects. - AmbientLight *ambient; - std::list shapes; - std::list lights; - - // Rendering stats - charles::Stats mStats; - - // Rendering output. - bool _is_rendered; - Color *pixels; -}; - -#endif diff --git a/src/scene.hh b/src/scene.hh new file mode 100644 index 0000000..53b594c --- /dev/null +++ b/src/scene.hh @@ -0,0 +1,86 @@ +/* scene.h + * vim: tw=80: + * Eryn Wells + */ + +#ifndef __SCENE_H__ +#define __SCENE_H__ + +#include +#include + +#include "camera.hh" +#include "light.h" +#include "object.hh" +#include "stats.hh" +#include "basics/basics.hh" + + +class Writer; + + +namespace charles { + +/** + * Scenes are the top level object in charles. Scenes contain objects, lights, a + * camera, etc. and can be rendered to pixel data and written to a file. + */ +struct Scene +{ + Scene(); + ~Scene(); + + UInt GetWidth() const; + void SetWidth(UInt w); + UInt GetHeight() const; + void SetHeight(UInt h); + + Camera::Ptr GetCamera() const; + void SetCamera(Camera::Ptr camera); + + void Write(Writer& writer, const std::string& filename); + + void Render(); + bool IsRendered() const; + const Color* GetPixels() const; + + AmbientLight& GetAmbient(); + void AddObject(Object::Ptr obj); + void AddLight(PointLight* light); + +private: + Color TraceRay(const basics::Ray &ray, + const int depth = 0, + const Double weight = 1.0); + + void LogCamera() const; + void LogObjects() const; + + /** Pixel width */ + UInt mWidth; + /** Pixel height */ + UInt mHeight; + + Camera::Ptr mCamera; + + /** Maximum depth of the ray tree */ + int mMaxDepth; + /** Minimum specular weight to apply before giving up */ + float mMinWeight; + + // Scene objects. + AmbientLight mAmbient; + std::list mObjects; + std::list mLights; + + // Rendering stats + charles::Stats mStats; + + // Rendering output. + bool mIsRendered; + Color *mPixels; +}; + +} /* namespace charles */ + +#endif From 4b396cabe8beffe30e61f21e1843d38beac4186c Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 19:30:47 -0700 Subject: [PATCH 42/92] Move Color over to basics --- src/basics/SConscript | 1 + src/basics/basics.hh | 1 + src/basics/color.cc | 214 ++++++++++++++++++++++++++++++++++++++ src/basics/color.hh | 54 ++++++++++ src/{light.h => light.hh} | 0 5 files changed, 270 insertions(+) create mode 100644 src/basics/color.cc create mode 100644 src/basics/color.hh rename src/{light.h => light.hh} (100%) diff --git a/src/basics/SConscript b/src/basics/SConscript index 2014565..0f47e1c 100644 --- a/src/basics/SConscript +++ b/src/basics/SConscript @@ -6,6 +6,7 @@ Import('env') files = [ + 'color.cc', 'matrix.cc', 'ray.cc', 'vector.cc', diff --git a/src/basics/basics.hh b/src/basics/basics.hh index fb956cd..ba66078 100644 --- a/src/basics/basics.hh +++ b/src/basics/basics.hh @@ -9,6 +9,7 @@ #ifndef __BASICS_BASICS_HH__ #define __BASICS_BASICS_HH__ +#include "basics/color.hh" #include "basics/matrix.hh" #include "basics/ray.hh" #include "basics/types.hh" diff --git a/src/basics/color.cc b/src/basics/color.cc new file mode 100644 index 0000000..a1dcb2f --- /dev/null +++ b/src/basics/color.cc @@ -0,0 +1,214 @@ +/* color.cc + * vim: set tw=80: + * Eryn Wells + */ + +#include + + +namespace charles { +namespace basics { + +/* + * Color::Color -- + */ +Color::Color() + : Color(0.0, 0.0, 0.0, 0.0) +{ } + + +/* + * Color::Color -- + */ +Color::Color(const Double& r, + const Double& g, + const Double& b, + const Double& a) + : red(r), + green(g), + blue(b), + alpha(a) +{ } + + +/* + * Color::operator*= -- + * Color::operator/= -- + * Color::operator+= -- + * Color::operator-= -- + * + * Perform the corresponding arithmetic operation on this color and the given scalar. These methods are destructive and + * a reference to this color is returned. + */ +Color & +Color::operator*=(const Double &rhs) +{ + red *= rhs; + green *= rhs; + blue *= rhs; + return *this; +} + +Color & +Color::operator/=(const Double &rhs) +{ + return *this *= (1.0 / rhs); +} + +Color & +Color::operator+=(const Double &rhs) +{ + red += rhs; + green += rhs; + blue += rhs; + alpha += rhs; + return *this; +} + +Color & +Color::operator-=(const Double &rhs) +{ + return *this += -rhs; +} + + +/* + * Color::operator* -- + * Color::operator/ -- + * Color::operator+ -- + * Color::operator- -- + * + * Perform the corresponding operation on a copy of this color and the given scalar. Return a new vector. + */ +Color +Color::operator*(const Double &rhs) + const +{ + return Color(*this) *= rhs; +} + +Color +Color::operator/(const Double &rhs) + const +{ + return Color(*this) /= rhs; +} + +Color +Color::operator+(const Double &rhs) + const +{ + return Color(*this) += rhs; +} + +Color +Color::operator-(const Double &rhs) + const +{ + return Color(*this) -= rhs; +} + + +/* + * Color::operator= -- + * + * Copy the given color's values into this color. Return a reference to this color. + */ +Color & +Color::operator=(const Color &rhs) +{ + red = rhs.red; + green = rhs.green; + blue = rhs.blue; + alpha = rhs.alpha; + return *this; +} + + +Color & +Color::operator*=(const Color &rhs) +{ + red *= rhs.red; + green *= rhs.green; + blue *= rhs.blue; + return *this; +} + +Color & +Color::operator/=(const Color &rhs) +{ + red *= (1.0 / rhs.red); + green *= (1.0 / rhs.green); + blue *= (1.0 / rhs.blue); + return *this; +} + +Color & +Color::operator+=(const Color &rhs) +{ + red += rhs.red; + green += rhs.green; + blue += rhs.blue; + alpha += rhs.alpha; + return *this; +} + +Color & +Color::operator-=(const Color &rhs) +{ + red -= rhs.red; + green -= rhs.green; + blue -= rhs.blue; + alpha -= rhs.alpha; + return *this; +} + + +Color +Color::operator*(const Color &rhs) + const +{ + return Color(*this) *= rhs; +} + +Color +Color::operator/(const Color &rhs) + const +{ + return Color(*this) /= rhs; +} + +Color +Color::operator+(const Color &rhs) + const +{ + return Color(*this) += rhs; +} + +Color +Color::operator-(const Color &rhs) + const +{ + return Color(*this) -= rhs; +} + + +const Color +operator*(const Double& lhs, + const Color& rhs) +{ + return rhs * lhs; +} + + +std::ostream & +operator<<(std::ostream& os, + const Color& c) +{ + // Stream colors like this: + os << "<" << c.red << ", " << c.green << ", " << c.blue << ", " << c.alpha << ">"; + return os; +} + +} /* namespace basics */ +} /* namespace charles */ diff --git a/src/basics/color.hh b/src/basics/color.hh new file mode 100644 index 0000000..ed4d0c2 --- /dev/null +++ b/src/basics/color.hh @@ -0,0 +1,54 @@ +/* color.hh + * vim: set tw=80: + * Eryn Wells + */ + +#include "basics/types.hh" + + +namespace charles { +namespace basics { + +struct Color +{ + Color(); + Color(const Double& r, const Double& g, const Double& b, const Double& a = 1.0); + + Color &operator*=(const Double &rhs); + Color &operator/=(const Double &rhs); + Color &operator+=(const Double &rhs); + Color &operator-=(const Double &rhs); + Color operator*(const Double &rhs) const; + Color operator/(const Double &rhs) const; + Color operator+(const Double &rhs) const; + Color operator-(const Double &rhs) const; + + Color &operator=(const Color &rhs); + + // These operators blend the two colors. + Color &operator*=(const Color &rhs); + Color &operator/=(const Color &rhs); + Color &operator+=(const Color &rhs); + Color &operator-=(const Color &rhs); + Color operator*(const Color &rhs) const; + Color operator/(const Color &rhs) const; + Color operator+(const Color &rhs) const; + Color operator-(const Color &rhs) const; + + static const Color Black; + static const Color White; + static const Color Red; + static const Color Green; + static const Color Blue; + + Double red, green, blue, alpha; +}; + + +const Color operator*(const Double &lhs, const Color &rhs); + +std::ostream &operator<<(std::ostream &os, const Color &c); + +} /* namespace basics */ +} /* namespace charles */ + diff --git a/src/light.h b/src/light.hh similarity index 100% rename from src/light.h rename to src/light.hh From d085a192e8af506d9343e53888f53cda9be4cd06 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 19:39:41 -0700 Subject: [PATCH 43/92] Clean up basics::Color --- src/basics/color.cc | 247 ++++++++++++++++++++++++++------------------ 1 file changed, 147 insertions(+), 100 deletions(-) diff --git a/src/basics/color.cc b/src/basics/color.cc index a1dcb2f..68d1a77 100644 --- a/src/basics/color.cc +++ b/src/basics/color.cc @@ -10,7 +10,7 @@ namespace charles { namespace basics { /* - * Color::Color -- + * charles::basics::Color::Color -- */ Color::Color() : Color(0.0, 0.0, 0.0, 0.0) @@ -18,7 +18,7 @@ Color::Color() /* - * Color::Color -- + * charles::basics::Color::Color -- */ Color::Color(const Double& r, const Double& g, @@ -32,90 +32,10 @@ Color::Color(const Double& r, /* - * Color::operator*= -- - * Color::operator/= -- - * Color::operator+= -- - * Color::operator-= -- - * - * Perform the corresponding arithmetic operation on this color and the given scalar. These methods are destructive and - * a reference to this color is returned. + * charles::basics::Color::operator= -- */ -Color & -Color::operator*=(const Double &rhs) -{ - red *= rhs; - green *= rhs; - blue *= rhs; - return *this; -} - -Color & -Color::operator/=(const Double &rhs) -{ - return *this *= (1.0 / rhs); -} - -Color & -Color::operator+=(const Double &rhs) -{ - red += rhs; - green += rhs; - blue += rhs; - alpha += rhs; - return *this; -} - -Color & -Color::operator-=(const Double &rhs) -{ - return *this += -rhs; -} - - -/* - * Color::operator* -- - * Color::operator/ -- - * Color::operator+ -- - * Color::operator- -- - * - * Perform the corresponding operation on a copy of this color and the given scalar. Return a new vector. - */ -Color -Color::operator*(const Double &rhs) - const -{ - return Color(*this) *= rhs; -} - -Color -Color::operator/(const Double &rhs) - const -{ - return Color(*this) /= rhs; -} - -Color -Color::operator+(const Double &rhs) - const -{ - return Color(*this) += rhs; -} - -Color -Color::operator-(const Double &rhs) - const -{ - return Color(*this) -= rhs; -} - - -/* - * Color::operator= -- - * - * Copy the given color's values into this color. Return a reference to this color. - */ -Color & -Color::operator=(const Color &rhs) +Color& +Color::operator=(const Color& rhs) { red = rhs.red; green = rhs.green; @@ -125,8 +45,102 @@ Color::operator=(const Color &rhs) } -Color & -Color::operator*=(const Color &rhs) +/* + * charles::basics::Color::operator*= -- + */ +Color& +Color::operator*=(const Double& rhs) +{ + red *= rhs; + green *= rhs; + blue *= rhs; + return *this; +} + + +/* + * charles::basics::Color::operator/= -- + */ +Color& +Color::operator/=(const Double& rhs) +{ + return *this *= (1.0 / rhs); +} + + +/* + * charles::basics::Color::operator+= -- + */ +Color& +Color::operator+=(const Double& rhs) +{ + red += rhs; + green += rhs; + blue += rhs; + alpha += rhs; + return *this; +} + + +/* + * charles::basics::Color::operator-= -- + */ +Color& +Color::operator-=(const Double& rhs) +{ + return *this += -rhs; +} + + +/* + * charles::basics::Color::operator* -- + */ +Color +Color::operator*(const Double& rhs) + const +{ + return Color(*this) *= rhs; +} + + +/* + * charles::basics::Color::operator/ -- + */ +Color +Color::operator/(const Double& rhs) + const +{ + return Color(*this) /= rhs; +} + + +/* + * charles::basics::Color::operator+ -- + */ +Color +Color::operator+(const Double& rhs) + const +{ + return Color(*this) += rhs; +} + + +/* + * charles::basics::Color::operator- -- + */ +Color +Color::operator-(const Double& rhs) + const +{ + return Color(*this) -= rhs; +} + + +/* + * charles::basics::Color::operator*= -- + */ +Color& +Color::operator*=(const Color& rhs) { red *= rhs.red; green *= rhs.green; @@ -134,17 +148,25 @@ Color::operator*=(const Color &rhs) return *this; } -Color & -Color::operator/=(const Color &rhs) + +/* + * charles::basics::Color::operator/= -- + */ +Color& +Color::operator/=(const Color& rhs) { - red *= (1.0 / rhs.red); - green *= (1.0 / rhs.green); - blue *= (1.0 / rhs.blue); + red /= rhs.red; + green /= rhs.green; + blue /= rhs.blue; return *this; } -Color & -Color::operator+=(const Color &rhs) + +/* + * charles::basics::Color::operator+= -- + */ +Color& +Color::operator+=(const Color& rhs) { red += rhs.red; green += rhs.green; @@ -153,8 +175,12 @@ Color::operator+=(const Color &rhs) return *this; } -Color & -Color::operator-=(const Color &rhs) + +/* + * charles::basics::Color::operator-= -- + */ +Color& +Color::operator-=(const Color& rhs) { red -= rhs.red; green -= rhs.green; @@ -164,35 +190,53 @@ Color::operator-=(const Color &rhs) } +/* + * charles::basics::Color::operator* -- + */ Color -Color::operator*(const Color &rhs) +Color::operator*(const Color& rhs) const { return Color(*this) *= rhs; } + +/* + * charles::basics::Color::operator/ -- + */ Color -Color::operator/(const Color &rhs) +Color::operator/(const Color& rhs) const { return Color(*this) /= rhs; } + +/* + * charles::basics::Color::operator+ -- + */ Color -Color::operator+(const Color &rhs) +Color::operator+(const Color& rhs) const { return Color(*this) += rhs; } + +/* + * charles::basics::Color::operator- -- + */ Color -Color::operator-(const Color &rhs) +Color::operator-(const Color& rhs) const { return Color(*this) -= rhs; } +/* + * charles::basics::operator* -- + */ const Color operator*(const Double& lhs, const Color& rhs) @@ -201,6 +245,9 @@ operator*(const Double& lhs, } +/* + * charles::basics::operator<< -- + */ std::ostream & operator<<(std::ostream& os, const Color& c) From e1ded8a9adfcedb8cade343082fb68a884ef76e8 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 20:04:42 -0700 Subject: [PATCH 44/92] Clean up for Lights (and AmbientLights) --- src/light.cc | 143 +++++++++++++++++++-------------------------------- src/light.hh | 59 ++++++++++----------- 2 files changed, 80 insertions(+), 122 deletions(-) diff --git a/src/light.cc b/src/light.cc index 9cdd977..5bb694d 100644 --- a/src/light.cc +++ b/src/light.cc @@ -1,112 +1,77 @@ /* light.cc - * - * Lights light the scene. - * + * vim: set tw=80: * Eryn Wells */ -#include "basics.h" -#include "light.h" -#include "object.h" +#include "light.hh" -#pragma mark - Ambient Lights -AmbientLight::AmbientLight() - : AmbientLight(Color::White) +using charles::basics::Color; + + +namespace charles { + +Light::Light(const Color& color, + const Double& intensity) + : mColor(color), + mIntensity(ClampIntensity(intensity)) { } -AmbientLight::AmbientLight(const Color &c) - : AmbientLight(c, 0.0) -{ } - - -AmbientLight::AmbientLight(const Color &c, const float &i) - : color(c), - intensity(i) +Color& +Light::GetColor() { - _clamp_intensity(); + return mColor; } -const Color & -AmbientLight::get_color() +const Color& +Light::GetColor() const { - return color; + return mColor; } -const float & -AmbientLight::get_intensity() +void +Light::SetColor(const Color& color) +{ + mColor = color; +} + + +Double +Light::GetIntensity() const { + return mIntensity; +} + + +void +Light::SetIntensity(const Double& intensity) +{ + mIntensity = ClampIntensity(intensity); +} + + +Color&& +Light::Contribution() + const +{ + return mColor * mIntensity; +} + + +Double +Light::ClampIntensity(const Double& intensity) +{ + if (intensity < 0.0) { + return 0.0; + } else if (intensity > 1.0) { + return 1.0; + } return intensity; } -void -AmbientLight::set_intensity(const float &i) -{ - intensity = i; - _clamp_intensity(); -} - - -Color -AmbientLight::compute_color_contribution() - const -{ - return color * intensity; -} - - -void -AmbientLight::_clamp_intensity() -{ - if (intensity < 0.0) { - intensity = 0.0; - } - else if (intensity > 1.0) { - intensity = 1.0; - } -} - -#pragma mark - Point Lights - -PointLight::PointLight() - : PointLight(Vector3()) -{ } - - -PointLight::PointLight(const Vector3 &o) - : PointLight(o, Color::White) -{ } - - -PointLight::PointLight(const Vector3 &o, - const Color &c) - : PointLight(o, c, 1.0) -{ } - - -PointLight::PointLight(const Vector3 &o, - const Color &c, - const float &i) - : AmbientLight(c, i), - mOrigin(o) -{ } - - -const Vector3& -PointLight::GetOrigin() - const -{ - return mOrigin; -} - - -void -PointLight::SetOrigin(const Vector3& origin) -{ - mOrigin = origin; -} +} /* namespace charles */ diff --git a/src/light.hh b/src/light.hh index 0749a0a..241ef33 100644 --- a/src/light.hh +++ b/src/light.hh @@ -1,53 +1,46 @@ -/* light.h - * - * Lights light the scene. - * +/* light.hh + * vim: set tw=80: * Eryn Wells */ #ifndef __LIGHT_H__ #define __LIGHT_H__ -#include "basics.h" +#include "basics/basics.hh" -class AmbientLight +namespace charles { + +struct Light { -public: - AmbientLight(); - AmbientLight(const Color &c); - AmbientLight(const Color &c, const float &i); + Light(const basics::Color& color, + const Double& intensity = 1.0); - const Color &get_color() const; - const float &get_intensity() const; - void set_intensity(const float &i); + basics::Color& GetColor(); + const basics::Color& GetColor() const; + void SetColor(basics::Color& color); - Color compute_color_contribution() const; + Double GetIntensity() const; + void SetIntensity(const Double& intensity); -protected: - Color color; - float intensity; + basics::Color&& Contribution() const; private: - void _clamp_intensity(); + Double ClampIntensity(const Double& intensity); + + /** The color of the light. */ + basics::Color mColor; + + /** + * The intensity of the light. Normal values range from 0.0 to 1.0, but + * they can be set higher. + */ + Double mIntensity; }; -class PointLight - : public AmbientLight -{ -public: - PointLight(); +typedef Light AmbientLight; - PointLight(const Vector3 &o); - PointLight(const Vector3 &o, const Color &c); - PointLight(const Vector3 &o, const Color &c, const float &i); - - const Vector3& GetOrigin() const; - void SetOrigin(const Vector3& origin); - -private: - Vector3 mOrigin; -}; +} /* namespace charles */ #endif From acdfb0fb60861aeb7a14b256de769520b9d7e3d2 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 20:22:35 -0700 Subject: [PATCH 45/92] Add PointLight in lightPoint.cc --- src/SConscript | 1 + src/lightPoint.cc | 35 +++++++++++++++++++++++++++++++++++ src/lightPoint.hh | 34 ++++++++++++++++++++++++++++++++++ 3 files changed, 70 insertions(+) create mode 100644 src/lightPoint.cc create mode 100644 src/lightPoint.hh diff --git a/src/SConscript b/src/SConscript index e0cb024..6aba113 100644 --- a/src/SConscript +++ b/src/SConscript @@ -21,6 +21,7 @@ files = [ 'basics.cc', 'camera.cc', 'light.cc', + 'lightPoint.cc', 'log.cc', 'material.cc', 'object.cc', diff --git a/src/lightPoint.cc b/src/lightPoint.cc new file mode 100644 index 0000000..7cee199 --- /dev/null +++ b/src/lightPoint.cc @@ -0,0 +1,35 @@ +/* lightPoint.cc + * vim: set tw=80: + * Eryn Wells + */ + +#include "lightPoint.hh" + + +using charles::basics::Vector4; + + +namespace charles { + +PointLight::PointLight(const Vector4& origin, + const Color& color) + : Light(color), + mOrigin(origin) +{ } + + +Vector4 +PointLight::GetOrigin() +{ + return mOrigin; +} + + +void +PointLight::SetOrigin(const Vector4& origin) +{ + mOrigin = origin; +} + +} /* namespace charles */ + diff --git a/src/lightPoint.hh b/src/lightPoint.hh new file mode 100644 index 0000000..efcfb49 --- /dev/null +++ b/src/lightPoint.hh @@ -0,0 +1,34 @@ +/* lightPoint.hh + * vim: set tw=80: + * Eryn Wells + */ + +#ifndef __LIGHTPOINT_HH__ +#define __LIGHTPOINT_HH__ + +#include "light.hh" + + +namespace charles { + +/** + * The simplest light source. Emits light in all directions uniformly, without + * falloff. + */ +class PointLight + : public Light +{ +public: + PointLight(const basics::Vector4 &origin, + const basics::Color& color); + + basics::Vector4& GetOrigin(); + void SetOrigin(const basics::Vector4& origin); + +private: + basics::Vector4 mOrigin; +}; + +} /* namespace charles */ + +#endif /* __LIGHTPOINT_HH__ */ From 3c3e707922fd4db3ce907dead2595d994d246d8a Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 20:23:08 -0700 Subject: [PATCH 46/92] Light has a shared_ptr type, and an overridable Contribution() --- src/light.hh | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/light.hh b/src/light.hh index 241ef33..22d0f2f 100644 --- a/src/light.hh +++ b/src/light.hh @@ -6,6 +6,8 @@ #ifndef __LIGHT_H__ #define __LIGHT_H__ +#include + #include "basics/basics.hh" @@ -13,6 +15,8 @@ namespace charles { struct Light { + typedef std::shared_ptr Ptr; + Light(const basics::Color& color, const Double& intensity = 1.0); @@ -23,7 +27,7 @@ struct Light Double GetIntensity() const; void SetIntensity(const Double& intensity); - basics::Color&& Contribution() const; + virtual basics::Color&& Contribution() const; private: Double ClampIntensity(const Double& intensity); From 080ee0d5805a8c0e20be67f0f5823304f5eb7a41 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 20:23:23 -0700 Subject: [PATCH 47/92] Remove Color and Vector3 from old basics --- src/basics.h | 40 ++-------------------------------------- 1 file changed, 2 insertions(+), 38 deletions(-) diff --git a/src/basics.h b/src/basics.h index e63d299..070ebfc 100644 --- a/src/basics.h +++ b/src/basics.h @@ -72,6 +72,7 @@ TooFar(const Double& value) } +#if 0 struct Vector3 { Vector3(); @@ -116,6 +117,7 @@ std::ostream &operator<<(std::ostream &os, const Vector3 &v); Vector3 LinearCombination(const Double k1, const Vector3& v1, const Double k2, const Vector3& v2, const Double k3, const Vector3& v3); +#endif #if 0 @@ -210,43 +212,5 @@ std::ostream &operator<<(std::ostream &os, const Ray &r); #endif -struct Color -{ - Color(); - Color(const float &r, const float &g, const float &b); - Color(const float &r, const float &g, const float &b, const float &a); - - Color &operator*=(const float &rhs); - Color &operator/=(const float &rhs); - Color &operator+=(const float &rhs); - Color &operator-=(const float &rhs); - Color operator*(const float &rhs) const; - Color operator/(const float &rhs) const; - Color operator+(const float &rhs) const; - Color operator-(const float &rhs) const; - - Color &operator=(const Color &rhs); - - // These operators blend the two colors. - Color &operator*=(const Color &rhs); - Color &operator/=(const Color &rhs); - Color &operator+=(const Color &rhs); - Color &operator-=(const Color &rhs); - Color operator*(const Color &rhs) const; - Color operator/(const Color &rhs) const; - Color operator+(const Color &rhs) const; - Color operator-(const Color &rhs) const; - - static const Color Black; - static const Color White; - static const Color Red; - static const Color Green; - static const Color Blue; - - float red, green, blue, alpha; -}; - -const Color operator*(const float &lhs, const Color &rhs); -std::ostream &operator<<(std::ostream &os, const Color &c); #endif From 161a635ab55cae333eadcb2c8668660b1a825762 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 20:24:00 -0700 Subject: [PATCH 48/92] reader.hh Fix up includes, put it in charles namespace --- src/reader.hh | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/src/reader.hh b/src/reader.hh index b235953..a6ef0e7 100644 --- a/src/reader.hh +++ b/src/reader.hh @@ -2,17 +2,18 @@ * vim: set tw=80: * Eryn Wells */ -/** - * Interface for an input file reader. - */ - #ifndef __READER_HH__ #define __READER_HH__ -#include "scene.h" +#include "scene.hh" +namespace charles { + +/** + * Interface for an input file reader. + */ struct Reader { Reader(Scene& scene) @@ -29,4 +30,6 @@ protected: Scene& mScene; }; +} /* namespace charles */ + #endif /* __READER_HH__ */ From f6680f993f932f239c0dee5a2fe0769608475c88 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 20:24:11 -0700 Subject: [PATCH 49/92] Clean up includes and old code in charles.cc --- src/charles.cc | 35 +++-------------------------------- 1 file changed, 3 insertions(+), 32 deletions(-) diff --git a/src/charles.cc b/src/charles.cc index 22260fe..00ccb37 100644 --- a/src/charles.cc +++ b/src/charles.cc @@ -10,16 +10,16 @@ #include "basics.h" #include "log.hh" -#include "light.h" +#include "light.hh" #include "reader_yaml.hh" -#include "scene.h" +#include "scene.hh" #include "writer_png.h" #define LOG_NAME "ROOT" #include "logModule.hh" -int verbosity = 0; +using namespace charles; static void @@ -38,35 +38,6 @@ main(int argc, Scene scene; - scene.get_ambient().set_intensity(1.0); - -#if 0 - Material *m1 = new Material(); - m1->set_diffuse_color(Color::Red); - Material *m2 = new Material(); - m2->set_diffuse_color(Color::Green); - Material *m3 = new Material(); - m3->set_diffuse_color(Color::Blue); - - // Make some spheres. - Sphere *s1 = new Sphere(Vector3(0, 0.5, 2), 0.33); - Sphere *s2 = new Sphere(Vector3(-0.33, 0, 2), 0.33); - Sphere *s3 = new Sphere(Vector3(0.33, 0, 2), 0.33); - s1->set_material(m1); - s2->set_material(m2); - s3->set_material(m3); - scene.add_shape(s1); - scene.add_shape(s2); - scene.add_shape(s3); - - // Make a plane - /* - Plane *p1 = new Plane(Vector3(0, 460, 400), Vector3(0, 1, 0.01)); - p1->set_material(m1); - scene.add_shape(p1); - */ -#endif - PointLight *l1 = new PointLight(Vector3(4.0, 6.0, 1.0), Color::White, 0.8); scene.add_light(l1); From b001ad2cf28d76e184ed2b8710612869ca4cc82a Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 20:24:18 -0700 Subject: [PATCH 50/92] light.hh include in scene.hh --- src/scene.hh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/scene.hh b/src/scene.hh index 53b594c..e1f428d 100644 --- a/src/scene.hh +++ b/src/scene.hh @@ -10,7 +10,7 @@ #include #include "camera.hh" -#include "light.h" +#include "light.hh" #include "object.hh" #include "stats.hh" #include "basics/basics.hh" From 42bef33775d47bc1362bf9e4b0838193287e4d96 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 20:24:45 -0700 Subject: [PATCH 51/92] Get rid of Color implementation in old basics.cc --- src/basics.cc | 214 -------------------------------------------------- 1 file changed, 214 deletions(-) diff --git a/src/basics.cc b/src/basics.cc index 1666c67..6e9ea43 100644 --- a/src/basics.cc +++ b/src/basics.cc @@ -534,217 +534,3 @@ operator<<(std::ostream &os, const Ray &r) } #pragma mark - Colors - -const Color Color::Black = Color(); -const Color Color::White = Color(1.0, 1.0, 1.0, 1.0); -const Color Color::Red = Color(1.0, 0.0, 0.0, 1.0); -const Color Color::Green = Color(0.0, 1.0, 0.0, 1.0); -const Color Color::Blue = Color(0.0, 0.0, 1.0, 1.0); - - -/* - * Color::Color -- - * - * Default constructor. Create a new Color with zeros for all components (black). - */ -Color::Color() - : Color(0.0, 0.0, 0.0, 0.0) -{ } - - -/* - * Color::Color -- - * - * Constructor. Create a new Color with the given RGB components. Alpha is 1.0. - */ -Color::Color(const float &r, const float &g, const float &b) - : Color(r, g, b, 1.0) -{ } - - -/* - * Color::Color -- - * - * Constructor. Create a new Color with the given components. - */ -Color::Color(const float &r, const float &g, const float &b, const float &a) - : red(r), green(g), blue(b), alpha(a) -{ } - - -/* - * Color::operator*= -- - * Color::operator/= -- - * Color::operator+= -- - * Color::operator-= -- - * - * Perform the corresponding arithmetic operation on this color and the given scalar. These methods are destructive and - * a reference to this color is returned. - */ -Color & -Color::operator*=(const float &rhs) -{ - red *= rhs; - green *= rhs; - blue *= rhs; - return *this; -} - -Color & -Color::operator/=(const float &rhs) -{ - return *this *= (1.0 / rhs); -} - -Color & -Color::operator+=(const float &rhs) -{ - red += rhs; - green += rhs; - blue += rhs; - alpha += rhs; - return *this; -} - -Color & -Color::operator-=(const float &rhs) -{ - return *this += -rhs; -} - - -/* - * Color::operator* -- - * Color::operator/ -- - * Color::operator+ -- - * Color::operator- -- - * - * Perform the corresponding operation on a copy of this color and the given scalar. Return a new vector. - */ -Color -Color::operator*(const float &rhs) - const -{ - return Color(*this) *= rhs; -} - -Color -Color::operator/(const float &rhs) - const -{ - return Color(*this) /= rhs; -} - -Color -Color::operator+(const float &rhs) - const -{ - return Color(*this) += rhs; -} - -Color -Color::operator-(const float &rhs) - const -{ - return Color(*this) -= rhs; -} - - -/* - * Color::operator= -- - * - * Copy the given color's values into this color. Return a reference to this color. - */ -Color & -Color::operator=(const Color &rhs) -{ - red = rhs.red; - green = rhs.green; - blue = rhs.blue; - alpha = rhs.alpha; - return *this; -} - - -Color & -Color::operator*=(const Color &rhs) -{ - red *= rhs.red; - green *= rhs.green; - blue *= rhs.blue; - return *this; -} - -Color & -Color::operator/=(const Color &rhs) -{ - red *= (1.0 / rhs.red); - green *= (1.0 / rhs.green); - blue *= (1.0 / rhs.blue); - return *this; -} - -Color & -Color::operator+=(const Color &rhs) -{ - red += rhs.red; - green += rhs.green; - blue += rhs.blue; - alpha += rhs.alpha; - return *this; -} - -Color & -Color::operator-=(const Color &rhs) -{ - red -= rhs.red; - green -= rhs.green; - blue -= rhs.blue; - alpha -= rhs.alpha; - return *this; -} - - -Color -Color::operator*(const Color &rhs) - const -{ - return Color(*this) *= rhs; -} - -Color -Color::operator/(const Color &rhs) - const -{ - return Color(*this) /= rhs; -} - -Color -Color::operator+(const Color &rhs) - const -{ - return Color(*this) += rhs; -} - -Color -Color::operator-(const Color &rhs) - const -{ - return Color(*this) -= rhs; -} - - -const Color -operator*(const float &lhs, const Color &rhs) -{ - return rhs * lhs; -} - - -std::ostream & -operator<<(std::ostream &os, const Color &c) -{ - // Stream colors like this: - os << "<" << c.red << ", " << c.green << ", " << c.blue << ", " << c.alpha << ">"; - return os; -} From 48e35dfc81c39c43c2fb0547bc15de05425f6ddc Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 20:31:18 -0700 Subject: [PATCH 52/92] Update material.{cc,hh} --- src/material.cc | 17 ++++++++--------- src/{material.h => material.hh} | 26 ++++++++++++++------------ 2 files changed, 22 insertions(+), 21 deletions(-) rename src/{material.h => material.hh} (71%) diff --git a/src/material.cc b/src/material.cc index a6ad762..a2edd8c 100644 --- a/src/material.cc +++ b/src/material.cc @@ -1,11 +1,12 @@ -/* material.h - * - * Materials are applied to shapes and determine color, texture mapping, shading, etc. - * +/* material.cc + * vim: set tw=80: * Eryn Wells */ -#include "material.h" +#include "material.hh" + + +using charles::basics::Color; namespace charles { @@ -36,9 +37,8 @@ Material::SetDiffuseIntensity(const Double& kd) } -const Color& +Color& Material::GetDiffuseColor() - const { return mDiffuseColor; } @@ -67,9 +67,8 @@ Material::SetSpecularIntensity(const Double& ks) } -const Color& +Color& Material::GetSpecularColor() - const { return mSpecularColor; } diff --git a/src/material.h b/src/material.hh similarity index 71% rename from src/material.h rename to src/material.hh index 3d52461..e154a32 100644 --- a/src/material.h +++ b/src/material.hh @@ -1,18 +1,20 @@ -/* material.h - * - * Materials are applied to shapes and determine color, texture mapping, shading, etc. - * +/* material.hh + * vim: set tw=80: * Eryn Wells */ -#ifndef __MATERIAL_H__ -#define __MATERIAL_H__ +#ifndef __MATERIAL_HH__ +#define __MATERIAL_HH__ + +#include "basics/basics.hh" -#include "basics.h" -#include "types.hh" namespace charles { +/** + * Materials are applied to shapes and determine color, texture mapping, + * shading, etc. + */ struct Material { enum class DiffuseShaderModel { @@ -29,14 +31,14 @@ struct Material Double GetDiffuseIntensity() const; void SetDiffuseIntensity(const Double& kd); - const Color& GetDiffuseColor() const; - void SetDiffuseColor(const Color& c); + basics::Color& GetDiffuseColor(); + void SetDiffuseColor(const basics::Color& c); Double GetSpecularIntensity() const; void SetSpecularIntensity(const Double& kd); - const Color &GetSpecularColor() const; - void SetSpecularColor(const Color& c); + basics::Color& GetSpecularColor(); + void SetSpecularColor(const basics::Color& c); private: void ClampParameter(Double& param); From c3da70cdd9daedbb6e507161a766050acbc6d760 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 20:34:23 -0700 Subject: [PATCH 53/92] Clean up some dependencies between scene, material, and color --- src/material.hh | 4 ++-- src/object.hh | 4 +--- src/scene.cc | 3 ++- src/scene.hh | 11 ++++++----- 4 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/material.hh b/src/material.hh index e154a32..64feb5c 100644 --- a/src/material.hh +++ b/src/material.hh @@ -46,12 +46,12 @@ private: // Diffuse parameters. DiffuseShaderModel mDiffuseModel; Double mDiffuseIntensity; - Color mDiffuseColor; + basics::Color mDiffuseColor; // Specular parameters. SpecularShaderModel mSpecularModel; Double mSpecularIntensity; - Color mSpecularColor; + basics::Color mSpecularColor; }; } /* namespace charles */ diff --git a/src/object.hh b/src/object.hh index 4ac3225..6696d72 100644 --- a/src/object.hh +++ b/src/object.hh @@ -10,10 +10,8 @@ #include #include -#include "material.h" +#include "material.hh" #include "stats.hh" -#include "texture.h" -#include "types.hh" #include "basics/basics.hh" diff --git a/src/scene.cc b/src/scene.cc index d64a05a..49d1aea 100644 --- a/src/scene.cc +++ b/src/scene.cc @@ -13,7 +13,7 @@ #include "scene.hh" #include "basics.h" -#include "light.h" +#include "light.hh" #include "log.hh" #include "object.hh" #include "writer.h" @@ -23,6 +23,7 @@ #include "logModule.hh" +using charles::basics::Color; using charles::basics::Ray; using charles::basics::Vector4; diff --git a/src/scene.hh b/src/scene.hh index e1f428d..7283d62 100644 --- a/src/scene.hh +++ b/src/scene.hh @@ -11,6 +11,7 @@ #include "camera.hh" #include "light.hh" +#include "lightPoint.hh" #include "object.hh" #include "stats.hh" #include "basics/basics.hh" @@ -42,16 +43,16 @@ struct Scene void Render(); bool IsRendered() const; - const Color* GetPixels() const; + const basics::Color* GetPixels() const; AmbientLight& GetAmbient(); void AddObject(Object::Ptr obj); void AddLight(PointLight* light); private: - Color TraceRay(const basics::Ray &ray, - const int depth = 0, - const Double weight = 1.0); + basics::Color TraceRay(const basics::Ray &ray, + const int depth = 0, + const Double weight = 1.0); void LogCamera() const; void LogObjects() const; @@ -78,7 +79,7 @@ private: // Rendering output. bool mIsRendered; - Color *mPixels; + basics::Color *mPixels; }; } /* namespace charles */ From 84cb27fa6f4cd7a63091c0e0c2334bf6b20ad727 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 20:45:45 -0700 Subject: [PATCH 54/92] Allow passing intensity in PointLight constructor --- src/lightPoint.cc | 5 +++-- src/lightPoint.hh | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/src/lightPoint.cc b/src/lightPoint.cc index 7cee199..dd52a3c 100644 --- a/src/lightPoint.cc +++ b/src/lightPoint.cc @@ -12,8 +12,9 @@ using charles::basics::Vector4; namespace charles { PointLight::PointLight(const Vector4& origin, - const Color& color) - : Light(color), + const Color& color, + const Double& intensity) + : Light(color, intensity), mOrigin(origin) { } diff --git a/src/lightPoint.hh b/src/lightPoint.hh index efcfb49..2881de3 100644 --- a/src/lightPoint.hh +++ b/src/lightPoint.hh @@ -20,7 +20,8 @@ class PointLight { public: PointLight(const basics::Vector4 &origin, - const basics::Color& color); + const basics::Color& color, + const Double& intensity); basics::Vector4& GetOrigin(); void SetOrigin(const basics::Vector4& origin); From 3a8c9557961c80aa26478bbb248d0b3d3612461f Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 20:46:14 -0700 Subject: [PATCH 55/92] Put the readers and writers in charles namespace --- src/reader_yaml.hh | 22 +++++++++++----------- src/scene.hh | 6 +++--- src/writer.h | 6 +++++- src/writer_png.h | 15 ++++++++++----- 4 files changed, 29 insertions(+), 20 deletions(-) diff --git a/src/reader_yaml.hh b/src/reader_yaml.hh index ecf4c09..62b5829 100644 --- a/src/reader_yaml.hh +++ b/src/reader_yaml.hh @@ -2,18 +2,18 @@ * vim: set tw=80: * Eryn Wells */ + +#ifndef __READERYAML_HH__ +#define __READERYAML_HH__ + +#include "reader.hh" +#include "scene.hh" + +namespace charles { + /** * An input file reader for YAML files. */ - - -#ifndef __READER_YAML_HH__ -#define __READER_YAML_HH__ - -#include "reader.hh" -#include "scene.h" - - struct YAMLReader : public Reader { @@ -21,9 +21,9 @@ struct YAMLReader : Reader(scene) { } - ~YAMLReader() { } - ssize_t read_file(const std::string& filename); }; +} /* namespace charles */ + #endif /* __READER_YAML_HH__ */ diff --git a/src/scene.hh b/src/scene.hh index 7283d62..14031e5 100644 --- a/src/scene.hh +++ b/src/scene.hh @@ -1,4 +1,4 @@ -/* scene.h +/* scene.hh * vim: tw=80: * Eryn Wells */ @@ -17,11 +17,11 @@ #include "basics/basics.hh" +namespace charles { + class Writer; -namespace charles { - /** * Scenes are the top level object in charles. Scenes contain objects, lights, a * camera, etc. and can be rendered to pixel data and written to a file. diff --git a/src/writer.h b/src/writer.h index 1d3bee1..981a17e 100644 --- a/src/writer.h +++ b/src/writer.h @@ -11,7 +11,9 @@ #include -class Scene; +namespace charles { + +struct Scene; class Writer @@ -24,4 +26,6 @@ public: virtual int write_scene(const Scene &scene, const std::string &filename) = 0; }; +} /* namespace charles */ + #endif diff --git a/src/writer_png.h b/src/writer_png.h index 5a3918f..0507aea 100644 --- a/src/writer_png.h +++ b/src/writer_png.h @@ -1,16 +1,19 @@ /* writer_png.h - * - * Declaration of the PNG writer. - * + * vim: set tw=80: * Eryn Wells */ -#ifndef __WRITER_PNG_H__ -#define __WRITER_PNG_H__ +#ifndef __WRITERPNG_HH__ +#define __WRITERPNG_HH__ #include "writer.h" +namespace charles { + +/** + * Write for producing PNG files. + */ class PNGWriter : public Writer { @@ -18,4 +21,6 @@ public: int write_scene(const Scene &scene, const std::string &filename); }; +} /* namespace charles */ + #endif From b7a9f07d5e153db30c3e45c48f545fe6939d5919 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 20:46:26 -0700 Subject: [PATCH 56/92] Lots of little niggling compiler errors --- src/basics/color.cc | 4 ++++ src/basics/vector.cc | 4 ++-- src/charles.cc | 11 ++++++----- 3 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/basics/color.cc b/src/basics/color.cc index 68d1a77..f9db9cd 100644 --- a/src/basics/color.cc +++ b/src/basics/color.cc @@ -5,6 +5,10 @@ #include +#include "basics/color.hh" + +#include "basics/types.hh" + namespace charles { namespace basics { diff --git a/src/basics/vector.cc b/src/basics/vector.cc index af09696..815196c 100644 --- a/src/basics/vector.cc +++ b/src/basics/vector.cc @@ -252,8 +252,8 @@ LinearCombination(const Double k1, const Vector4& v1, /* * charles::basics::operator<< -- */ -std::ostream & -operator<<(std::ostream &os, const Vector3 &v) +std::ostream& +operator<<(std::ostream& os, const Vector4& v) { // Stream the vector like this: os << "<" << v.X() << ", " << v.Y() << ", " << v.Z() << ">"; diff --git a/src/charles.cc b/src/charles.cc index 00ccb37..d684b86 100644 --- a/src/charles.cc +++ b/src/charles.cc @@ -8,18 +8,19 @@ #include #include -#include "basics.h" #include "log.hh" #include "light.hh" #include "reader_yaml.hh" #include "scene.hh" #include "writer_png.h" +#include "basics/basics.hh" #define LOG_NAME "ROOT" #include "logModule.hh" using namespace charles; +using namespace charles::basics; static void @@ -38,8 +39,8 @@ main(int argc, Scene scene; - PointLight *l1 = new PointLight(Vector3(4.0, 6.0, 1.0), Color::White, 0.8); - scene.add_light(l1); + PointLight *l1 = new PointLight(Vector4(4.0, 6.0, 1.0), Color::White, 0.8); + scene.AddLight(l1); std::string logFilename; unsigned int logLevel = 0; @@ -96,11 +97,11 @@ main(int argc, /* Call tracer. */ LOG_INFO << "Beginning render"; - scene.render(); + scene.Render(); /* Write rendered scene to PNG file. */ PNGWriter writer; - scene.write(writer, outfile); + scene.Write(writer, outfile); if (logLevel > 0) { Log::Close(); From ef9b9d04c8e5ae1dfca3b1059b0cd827ac076341 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 20:53:04 -0700 Subject: [PATCH 57/92] Put all the parsers in the charles namespace --- src/yaml/cameraParser.cc | 4 +++- src/yaml/cameraParser.hh | 2 ++ src/yaml/objectParser.cc | 5 ++--- src/yaml/objectParser.hh | 2 ++ src/yaml/parsers.cc | 2 ++ src/yaml/parsers.hh | 4 +++- src/yaml/scalarMappingParser.cc | 2 ++ src/yaml/scalarMappingParser.hh | 2 ++ src/yaml/sceneParser.cc | 2 ++ src/yaml/sceneParser.hh | 2 ++ src/yaml/vectorParser.cc | 2 ++ src/yaml/vectorParser.hh | 2 ++ 12 files changed, 26 insertions(+), 5 deletions(-) diff --git a/src/yaml/cameraParser.cc b/src/yaml/cameraParser.cc index 2ae49fa..34e8328 100644 --- a/src/yaml/cameraParser.cc +++ b/src/yaml/cameraParser.cc @@ -5,11 +5,12 @@ #include -#include "camera.h" +#include "camera.hh" #include "yaml/cameraParser.hh" #include "yaml/vectorParser.hh" +namespace charles { namespace yaml { CameraParser::CameraParser(Scene& scene, @@ -207,3 +208,4 @@ CameraParser::HandleUpEvent(yaml_event_t& event) } } /* namespace yaml */ +} /* namespace charles */ diff --git a/src/yaml/cameraParser.hh b/src/yaml/cameraParser.hh index 6724b16..2578da0 100644 --- a/src/yaml/cameraParser.hh +++ b/src/yaml/cameraParser.hh @@ -12,6 +12,7 @@ struct Camera; +namespace charles { namespace yaml { struct CameraParser @@ -53,6 +54,7 @@ private: }; } /* namespace yaml */ +} /* namespace charles */ #endif /* __YAML_CAMERAPARSER_HH__ */ diff --git a/src/yaml/objectParser.cc b/src/yaml/objectParser.cc index f21b511..eba3e6e 100644 --- a/src/yaml/objectParser.cc +++ b/src/yaml/objectParser.cc @@ -19,9 +19,7 @@ #include "yaml/vectorParser.hh" -using namespace charles; - - +namespace charles { namespace yaml { ObjectParser::ObjectParser(Scene& scene, @@ -280,3 +278,4 @@ ObjectParser::HandleDistanceEvent(yaml_event_t& event) } } /* namespace yaml */ +} /* namespace charles */ diff --git a/src/yaml/objectParser.hh b/src/yaml/objectParser.hh index 80bf7e8..ca0a077 100644 --- a/src/yaml/objectParser.hh +++ b/src/yaml/objectParser.hh @@ -13,6 +13,7 @@ #include "yaml/scalarMappingParser.hh" +namespace charles { namespace yaml { struct ObjectParser @@ -66,5 +67,6 @@ private: }; } /* namespace yaml */ +} /* namespace charles */ #endif /* __YAML_OBJECTPARSER_HH__ */ diff --git a/src/yaml/parsers.cc b/src/yaml/parsers.cc index 4267247..5106241 100644 --- a/src/yaml/parsers.cc +++ b/src/yaml/parsers.cc @@ -13,6 +13,7 @@ #include "parsers.hh" +namespace charles { namespace yaml { #pragma mark Parser @@ -81,3 +82,4 @@ template<> const char* ScalarParserTraits::fmt = "%lf"; } /* namespace yaml */ +} /* namespace charles */ diff --git a/src/yaml/parsers.hh b/src/yaml/parsers.hh index 2f3b759..46e0c6e 100644 --- a/src/yaml/parsers.hh +++ b/src/yaml/parsers.hh @@ -15,9 +15,10 @@ #include "yaml.h" -#include "scene.h" +#include "scene.hh" +namespace charles { namespace yaml { struct Parser; @@ -144,5 +145,6 @@ ParseScalar(const std::string& scalar, } } /* namespace yaml */ +} /* namespace charles */ #endif /* __YAML_PARSERS_HH__ */ diff --git a/src/yaml/scalarMappingParser.cc b/src/yaml/scalarMappingParser.cc index f453f2d..d04d6ea 100644 --- a/src/yaml/scalarMappingParser.cc +++ b/src/yaml/scalarMappingParser.cc @@ -12,6 +12,7 @@ #include "scalarMappingParser.hh" +namespace charles { namespace yaml { ScalarMappingParser::ScalarMappingParser(Scene& scene, @@ -83,3 +84,4 @@ ScalarMappingParser::GetShouldExpectKey() } } /* namespace yaml */ +} /* namespace charles */ diff --git a/src/yaml/scalarMappingParser.hh b/src/yaml/scalarMappingParser.hh index 9e8fa8b..38ef759 100644 --- a/src/yaml/scalarMappingParser.hh +++ b/src/yaml/scalarMappingParser.hh @@ -17,6 +17,7 @@ #include "yaml/parsers.hh" +namespace charles { namespace yaml { struct ScalarMappingParser @@ -40,5 +41,6 @@ private: }; } /* namespace yaml */ +} /* namespace charles */ #endif /* __YAML_SCALARMAPPINGPARSER_HH__ */ diff --git a/src/yaml/sceneParser.cc b/src/yaml/sceneParser.cc index a435df8..6b99230 100644 --- a/src/yaml/sceneParser.cc +++ b/src/yaml/sceneParser.cc @@ -15,6 +15,7 @@ #include "vectorParser.hh" +namespace charles { namespace yaml { SceneParser::SceneParser(Scene& scene, @@ -137,3 +138,4 @@ SceneParser::HandleObjectsEvent(yaml_event_t& event) } } /* namespace yaml */ +} /* namespace charles */ diff --git a/src/yaml/sceneParser.hh b/src/yaml/sceneParser.hh index 2279669..be62be8 100644 --- a/src/yaml/sceneParser.hh +++ b/src/yaml/sceneParser.hh @@ -15,6 +15,7 @@ #include "scalarMappingParser.hh" +namespace charles { namespace yaml { struct SceneParser @@ -43,5 +44,6 @@ private: }; } /* namespace yaml */ +} /* namespace charles */ #endif /* __YAML_SCENE_PARSER_HH__ */ diff --git a/src/yaml/vectorParser.cc b/src/yaml/vectorParser.cc index 5409f97..3a33577 100644 --- a/src/yaml/vectorParser.cc +++ b/src/yaml/vectorParser.cc @@ -8,6 +8,7 @@ #include "yaml/vectorParser.hh" +namespace charles { namespace yaml { Vector3Parser::Vector3Parser(Scene& scene, @@ -55,3 +56,4 @@ ColorParser::~ColorParser() { } } /* namespace yaml */ +} /* namespace charles */ diff --git a/src/yaml/vectorParser.hh b/src/yaml/vectorParser.hh index 2eb1bb5..4e5374e 100644 --- a/src/yaml/vectorParser.hh +++ b/src/yaml/vectorParser.hh @@ -16,6 +16,7 @@ #include "parsers.hh" +namespace charles { namespace yaml { /** @@ -102,5 +103,6 @@ struct ColorParser }; } /* namespace yaml */ +} /* namespace charles */ #endif /* __YAML_VECTOR_PARSER_HH__ */ From 6c23fa9f32f0dab57006a4404e0e861ba5915267 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 21:21:27 -0700 Subject: [PATCH 58/92] Get rid of the old basics! --- src/basics.cc | 536 -------------------------------------------------- src/basics.h | 216 -------------------- 2 files changed, 752 deletions(-) delete mode 100644 src/basics.cc delete mode 100644 src/basics.h diff --git a/src/basics.cc b/src/basics.cc deleted file mode 100644 index 6e9ea43..0000000 --- a/src/basics.cc +++ /dev/null @@ -1,536 +0,0 @@ -/* basics.c - * - * Definition of basic types. - * - * - Vector3 is a three tuple vector of x, y, and z. - * - Ray is a vector plus a direction. - * - Color is a four tuple of red, green, blue, and alpha. - * - * Eryn Wells - */ - -#include -#include -#include - -#include "basics.h" - -#pragma mark - Vectors - -const Vector3 Vector3::Zero = Vector3(); -const Vector3 Vector3::X = Vector3(1, 0, 0); -const Vector3 Vector3::Y = Vector3(0, 1, 0); -const Vector3 Vector3::Z = Vector3(0, 0, 1); - - -/* - * Vector3::Vector3 -- - * - * Default constructor. Create a zero vector. - */ -Vector3::Vector3() - : Vector3(0.0, 0.0, 0.0) -{ } - - -/* - * Vector3::Vector3 -- - * - * Constructor. Create a vector consisting of the given coordinates. - */ -Vector3::Vector3(Double _x, Double _y, Double _z) - : x(_x), y(_y), z(_z) -{ } - - -/* - * Vector3::operator= -- - * - * Copy the given vector's values into this vector. Return a reference to this vector. - */ -Vector3 & -Vector3::operator=(const Vector3 &v) -{ - x = v.x; - y = v.y; - z = v.z; - return *this; -} - - -/* - * Vector3::operator*= -- - * Vector3::operator/= -- - * Vector3::operator+= -- - * Vector3::operator-= -- - * - * Perform the corresponding arithmetic operation on this vector and the given vector. These methods are destructive and - * a reference to this vector is returned. - */ -Vector3 & -Vector3::operator*=(const Double &rhs) -{ - x *= rhs; - y *= rhs; - z *= rhs; - return *this; -} - -Vector3 & -Vector3::operator/=(const Double &rhs) -{ - return *this *= (1.0f / rhs); -} - -Vector3 & -Vector3::operator+=(const Vector3 &rhs) -{ - x += rhs.x; - y += rhs.y; - z += rhs.z; - return *this; -} - -Vector3 & -Vector3::operator-=(const Vector3 &rhs) -{ - return *this += -rhs; -} - - -/* - * Vector3::operator* -- - * Vector3::operator/ -- - * Vector3::operator+ -- - * Vector3::operator- -- - * - * Perform the corresponding operation on a copy of this vector. Return a new vector. - */ -Vector3 -Vector3::operator*(const Double &rhs) - const -{ - return Vector3(*this) *= rhs; -} - -Vector3 -Vector3::operator/(const Double &rhs) - const -{ - return Vector3(*this) /= rhs; -} - -Vector3 -Vector3::operator+(const Vector3 &rhs) - const -{ - return Vector3(*this) += rhs; -} - -Vector3 -Vector3::operator-(const Vector3 &rhs) - const -{ - return Vector3(*this) -= rhs; -} - - -/* - * Vector3::operator- -- - * - * Negate this vector. Return a new vector. - */ -Vector3 -Vector3::operator-() - const -{ - return Vector3(-x, -y, -z); -} - - -/* - * Vector3::operator== -- - * Vector3::operator!= -- - * - * Compute boolean equality and non-equality of this and the given vectors. - */ -bool -Vector3::operator==(const Vector3 &rhs) - const -{ - return x == rhs.x && y == rhs.y && z == rhs.z; -} - -bool -Vector3::operator!=(const Vector3 &rhs) - const -{ - return !(*this == rhs); -} - - -/* - * Vector3::length2 -- - * - * Compute and return the length-squared of this vector. - */ -Double -Vector3::length2() - const -{ - return x*x + y*y + z*z; -} - - -/* - * Vector3::length -- - * - * Compute and return the length of this vector. - */ -Double -Vector3::length() - const -{ - return sqrt(length2()); -} - - -/* - * Vector3::dot -- - * - * Compute and return the dot product of this and the given vectors. - */ -Double -Vector3::dot(const Vector3 &v) - const -{ - return x*v.x + y*v.y + z*v.z; -} - - -/* - * Vector3::cross -- - * - * Compute and return the cross product of this and the given vectors. - */ -Vector3 -Vector3::cross(const Vector3 &v) - const -{ - return Vector3(y*v.z - z*v.y, z*v.x - x*v.z, x*v.y - y*v.x); -} - - -/* - * Vector3::normalize -- - */ -Vector3 & -Vector3::normalize() -{ - // Use the overloaded /= compound operator to do this. - return *this /= length(); -} - - -/* - * Vector3::normalized -- - */ -Vector3 -Vector3::normalized() - const -{ - return *this / length(); -} - - -/* - * operator* -- - * - * Multiply the given float by the given vector. Return a new vector. - */ -const Vector3 -operator*(const Double &lhs, const Vector3 &rhs) -{ - return rhs * lhs; -} - - -std::ostream & -operator<<(std::ostream &os, const Vector3 &v) -{ - // Stream the vector like this: - os << "<" << v.x << ", " << v.y << ", " << v.z << ">"; - return os; -} - - -Vector3 -LinearCombination(const Double k1, const Vector3& v1, - const Double k2, const Vector3& v2, - const Double k3, const Vector3& v3) -{ - return Vector3(k1 * v1.x + k2 * v2.x + k3 * v3.x, - k1 * v1.y + k2 * v2.y + k3 * v3.y, - k1 * v1.z + k2 * v2.z + k3 * v3.z); -} - -#pragma mark - Matrices - -#if 0 -/* static */ Matrix4 -Matrix4::Zero() -{ - Matrix4 m; - memset(m.mCells, 0, 16 * sizeof(Double)); - return m; -} - - -/* static */ Matrix4 -Matrix4::Identity() -{ - Matrix4 m = Zero(); - for (int i = 0; i < 4; i++) { - m.mCells[i * 4 + i] = 1.0; - } - return m; -} - - -/* static */ Matrix4 -Matrix4::Translation(Double x, - Double y, - Double z) -{ - Matrix4 m = Identity(); - m.mCells[3] = x; - m.mCells[7] = y; - m.mCells[11] = z; - return m; -} - - -/* static */ Matrix4 -Matrix4::Rotation(Double x, - Double y, - Double z) -{ - Matrix4 m = Identity(); - - if (x == 0.0 && y == 0.0 && z == 0.0) { - /* No rotation, just return the identity matrix. */ - } else if (x != 0.0 && y == 0.0 && z == 0.0) { - /* - * Fill in m with values for an X rotation matrix. - * - * [1 0 0 0] - * [0 cos(x) -sin(x) 0] - * [0 sin(x) cos(x) 0] - * [0 0 0 1] - */ - Double cosX = std::cos(x); - Double sinX = std::sin(x); - m.mCells[5] = cosX; - m.mCells[6] = -sinX; - m.mCells[9] = sinX; - m.mCells[10] = cosX; - } else if (x == 0.0 && y != 0.0 && z == 0.0) { - /* - * Fill in m with values for a Y rotation matrix. - * - * [ cos(y) 0 sin(y) 0] - * [ 0 1 0 0] - * [-sin(y) 0 cos(y) 0] - * [ 0 0 0 1] - */ - Double cosY = std::cos(y); - Double sinY = std::sin(y); - m.mCells[0] = cosY; - m.mCells[2] = sinY; - m.mCells[8] = -sinY; - m.mCells[10] = cosY; - } else if (x == 0.0 && y == 0.0 && z != 0.0) { - /* - * Fill in m with values for a Z rotation matrix. - * - * [cos(z) -sin(z) 0 0] - * [sin(z) cos(z) 0 0] - * [ 0 0 1 0] - * [ 0 0 0 1] - */ - Double cosZ = std::cos(z); - Double sinZ = std::sin(z); - m.mCells[0] = cosZ; - m.mCells[1] = -sinZ; - m.mCells[4] = sinZ; - m.mCells[5] = cosZ; - } else { - /* - * TODO: Rotation in more than one dimension. So do a general rotation - * matrix. There's some magic way to do this with matrix multiplication - * that avoids gimbal lock. I should figure out how to do it properly. - */ - assert(0); - } - - return m; -} - - -/* - * Matrix4::Matrix4 -- - */ -Matrix4::Matrix4() - : mCells() -{ } - - -/* - * Matrix4::Matrix4 -- - */ -Matrix4::Matrix4(const Double cells[16]) - : mCells() -{ - memcpy(mCells, cells, 16 * sizeof(Double)); -} - - -/* - * Matrix4::Matrix4 -- - */ -Matrix4::Matrix4(const Matrix4& rhs) - : Matrix4(rhs.mCells) -{ } - - -/* - * Matrix4::operator() -- - */ -Double& -Matrix4::operator()(const unsigned int row, - const unsigned int col) -{ - assert(row < 4 && col < 4); - return mCells[4*row + col]; -} - - -/* - * Matrix4::operator* -- - */ -Matrix4 -Matrix4::operator*(const Double rhs) - const -{ - return Matrix4(*this) *= rhs; -} - - -/* - * Matrix4::operator*= -- - */ -Matrix4& -Matrix4::operator*=(const Double rhs) -{ - for (int i = 0; i < 16; i++) { - mCells[i] *= rhs; - } - return *this; -} - - -/* - * Matrix4::operator* -- - */ -Matrix4 -Matrix4::operator*(const Matrix4& rhs) - const -{ - return Matrix4(*this) *= rhs; -} - - -/* - * Matrix4::operator*= - */ -Matrix4& -Matrix4::operator*=(const Matrix4& rhs) -{ - Matrix4 lhs(*this); - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - /* Each cell is Sigma(k=0, 4)(lhs[ik] * rhs[kj]) */ - const int cell = i*4 + j; - mCells[cell] = 0.0; - for (int k = 0; k < 4; k++) { - mCells[cell] += lhs.mCells[i*4 + k] * rhs.mCells[k*4 + j]; - } - } - } - return *this; -} - - -/* - * Matrix4::CArray -- - */ -const Double* -Matrix4::CArray() - const -{ - return mCells; -} - - -Matrix4 -operator*(const Double rhs, - const Matrix4& lhs) -{ - /* Scalar multiplication is commutative. */ - return lhs * rhs; -} -#endif - -#pragma mark - Rays - -/* - * Ray::Ray -- - * - * Default constructor. Create a ray at the origin (0, 0, 0) with direction (0, 0, 0). - */ -Ray::Ray() - : Ray(Vector3::Zero, Vector3::Zero) -{ } - - -/* - * Ray::Ray -- - * - * Constructor. Create a ray with the given origin and direction. - */ -Ray::Ray(Vector3 o, Vector3 d) - : origin(o), direction(d) -{ } - - -/* - * Ray::parameterize -- - * - * Compute and return the point given by parameterizing this Ray by time t. - */ -Vector3 -Ray::parameterize(const Double& t) - const -{ - return origin + t * direction; -} - - -std::ostream & -operator<<(std::ostream &os, const Ray &r) -{ - os << "[Ray " << r.origin << " " << r.direction << "]"; - return os; -} - -#pragma mark - Colors diff --git a/src/basics.h b/src/basics.h deleted file mode 100644 index 070ebfc..0000000 --- a/src/basics.h +++ /dev/null @@ -1,216 +0,0 @@ -/* basics.h - * vim: set tw=80: - * Eryn Wells - */ - -#ifndef __BASICS_H__ -#define __BASICS_H__ - -#include -#include - -#include "types.hh" - -/* - * XXX: THIS SHOULD NOT BE HERE. REMOVE IT WHEN MOVING TO CHARLES NAMESPACE IS - * DONE. - */ -using charles::Double; - - -/** - * A very small constant. If a value is between EPSILON and 0.0, it is - * considered to be zero. - */ -const Double EPSILON = 1.0e-10; - -/** - * The maximum distance a ray can travel. This is the maximum value t can be. - */ -const Double MAX_DISTANCE = 1.0e7; - -/** - * Determine if the value is "close enough" to zero. Takes the absolute value - * and compares it to `EPSILON`. - * - * @see EPSILON - * - * @param [in] value The value to check - * @returns `true` if the value is close enough to zero - */ -template -inline bool -NearZero(const T value) -{ - return std::fabs(value) < EPSILON; -} - - -/** - * Determine if two values are "close enough" to be considered equal. Subtracts - * one from the other and checks if the result is near zero. - * - * @see NearZero - * - * @param [in] left The left parameter - * @param [in] right The right parameter - * @returns `true` if the values are close enough to be equal - */ -template -inline bool -NearlyEqual(const T left, - const T right) -{ - return NearZero(left - right); -} - - -inline bool -TooFar(const Double& value) -{ - return value > MAX_DISTANCE; -} - - -#if 0 -struct Vector3 -{ - Vector3(); - Vector3(Double x, Double y, Double z); - - Vector3 &operator=(const Vector3 &v); - Vector3 &operator*=(const Double &rhs); - Vector3 &operator/=(const Double &rhs); - Vector3 &operator+=(const Vector3 &rhs); - Vector3 &operator-=(const Vector3 &rhs); - Vector3 operator*(const Double &rhs) const; - Vector3 operator/(const Double &rhs) const; - Vector3 operator+(const Vector3 &rhs) const; - Vector3 operator-(const Vector3 &rhs) const; - Vector3 operator-() const; - - bool operator==(const Vector3 &rhs) const; - bool operator!=(const Vector3 &rhs) const; - - Double length2() const; - Double length() const; - Double dot(const Vector3 &v) const; - Vector3 cross(const Vector3 &v) const; - - /** Normalize and return a reference to this vector. */ - Vector3 &normalize(); - - /** Return a copy of this vector, normalized. Does not modify this vector. */ - Vector3 normalized() const; - - static const Vector3 Zero; - // Unit vectors in each of the three cartesian directions. - static const Vector3 X, Y, Z; - - Double x, y, z; -}; - -const Vector3 operator*(const Double &lhs, const Vector3 &rhs); -std::ostream &operator<<(std::ostream &os, const Vector3 &v); - - -Vector3 LinearCombination(const Double k1, const Vector3& v1, - const Double k2, const Vector3& v2, - const Double k3, const Vector3& v3); -#endif - - -#if 0 -struct Matrix4 -{ - /** Create a 4x4 zero matrix. That is, all cells are 0. */ - static Matrix4 Zero(); - - /** Create a 4x4 identity matrix. */ - static Matrix4 Identity(); - - Matrix4(); - Matrix4(const Double cells[16]); - Matrix4(const Matrix4& rhs); - - /** - * Create a 4x4 translation matrix. A translation matrix looks like this: - * - * [1 0 0 x] - * [0 1 0 y] - * [0 0 1 z] - * [0 0 0 1] - * - * @param [in] x X translation - * @param [in] y Y translation - * @param [in] z Z translation - * @returns The translation matrix - */ - static Matrix4 Translation(Double x, Double y, Double z); - - /** - * Create a 4x4 rotation matrix. A rotation matrices are quite complicated. - * - * @param [in] x X rotation angle in radians - * @param [in] y Y rotation angle in radians - * @param [in] z Z rotation angle in radians - * @returns The rotation matrix - */ - static Matrix4 Rotation(Double x, Double y, Double z); - - /** - * Get the value of the cell at (row, col). - * - * @param [in] row The row, must be less than the matrix's width - * @param [in] col The column, must be less than the matrix's height - * @returns The value of the cell at (row, col) - */ - Double& operator()(const unsigned int row, const unsigned int col); - - /** - * Scalar multiplication. - * - * @param [in] rhs The scalar factor - * @returns A copy of this matrix, multiplied by the scalar - */ - Matrix4 operator*(const Double rhs) const; - - /** - * Scalar multiplication. Multiplies this matrix by the given factor. - * - * @param [in] rhs The scalar factor - * @returns *this - */ - Matrix4& operator*=(const Double rhs); - - Matrix4 operator*(const Matrix4& rhs) const; - Matrix4& operator*=(const Matrix4& rhs); - - const Double* CArray() const; - -private: - Double mCells[16]; -}; - - -Matrix4 operator*(const Double lhs, const Matrix4& rhs); -#endif - - -#if 0 -struct Ray -{ - Ray(); - Ray(Vector3 o, Vector3 d); - - Vector3 parameterize(const Double& t) const; - - Vector3 origin, direction; -}; - -std::ostream &operator<<(std::ostream &os, const Ray &r); -#endif - - - -#endif From bb789476b69e115fd436be34fc6d6aada976f535 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 21:21:57 -0700 Subject: [PATCH 59/92] New basics gets the remainder of the stuff from old basics EPSILON, MAX_DISTANCE, NearZeor, NearlyEqual, TooFar. --- src/basics/basics.hh | 56 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/src/basics/basics.hh b/src/basics/basics.hh index ba66078..d6b91e1 100644 --- a/src/basics/basics.hh +++ b/src/basics/basics.hh @@ -9,10 +9,66 @@ #ifndef __BASICS_BASICS_HH__ #define __BASICS_BASICS_HH__ +#include + #include "basics/color.hh" #include "basics/matrix.hh" #include "basics/ray.hh" #include "basics/types.hh" #include "basics/vector.hh" + +/** + * A very small constant. If a value is between EPSILON and 0.0, it is + * considered to be zero. + */ +const Double EPSILON = 1.0e-10; + +/** + * The maximum distance a ray can travel. This is the maximum value t can be. + */ +const Double MAX_DISTANCE = 1.0e7; + +/** + * Determine if the value is "close enough" to zero. Takes the absolute value + * and compares it to `EPSILON`. + * + * @see EPSILON + * + * @param [in] value The value to check + * @returns `true` if the value is close enough to zero + */ +template +inline bool +NearZero(const T value) +{ + return std::fabs(value) < EPSILON; +} + + +/** + * Determine if two values are "close enough" to be considered equal. Subtracts + * one from the other and checks if the result is near zero. + * + * @see NearZero + * + * @param [in] left The left parameter + * @param [in] right The right parameter + * @returns `true` if the values are close enough to be equal + */ +template +inline bool +NearlyEqual(const T left, + const T right) +{ + return NearZero(left - right); +} + + +inline bool +TooFar(const Double& value) +{ + return value > MAX_DISTANCE; +} + #endif /* __BASICS_BASICS_HH__ */ From a97e7a6d2ea4f4c2a31f8c86e8750165138686ad Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 21:22:12 -0700 Subject: [PATCH 60/92] Lights get virtual destructor and correct types --- src/light.cc | 4 ++++ src/light.hh | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/light.cc b/src/light.cc index 5bb694d..847602f 100644 --- a/src/light.cc +++ b/src/light.cc @@ -18,6 +18,10 @@ Light::Light(const Color& color, { } +Light::~Light() +{ } + + Color& Light::GetColor() { diff --git a/src/light.hh b/src/light.hh index 22d0f2f..3175178 100644 --- a/src/light.hh +++ b/src/light.hh @@ -20,9 +20,11 @@ struct Light Light(const basics::Color& color, const Double& intensity = 1.0); + virtual ~Light(); + basics::Color& GetColor(); const basics::Color& GetColor() const; - void SetColor(basics::Color& color); + void SetColor(const basics::Color& color); Double GetIntensity() const; void SetIntensity(const Double& intensity); From 43c8bd95c68771669d3e50fea999b445f116526f Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 21:22:40 -0700 Subject: [PATCH 61/92] Remove basics.cc from the build --- src/SConscript | 1 - 1 file changed, 1 deletion(-) diff --git a/src/SConscript b/src/SConscript index 6aba113..fc8bb07 100644 --- a/src/SConscript +++ b/src/SConscript @@ -18,7 +18,6 @@ for d in subdirs: files = [ - 'basics.cc', 'camera.cc', 'light.cc', 'lightPoint.cc', From bf91fff5a2a8f13fd3b20562ec21dcbfd1a96db6 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 21:23:11 -0700 Subject: [PATCH 62/92] More compiler fixups --- src/lightPoint.cc | 3 ++- src/object.cc | 2 +- src/reader_yaml.cc | 3 +++ src/scene.cc | 7 +++---- src/writer_png.cc | 27 +++++++++++++++++---------- src/yaml/cameraParser.cc | 37 ++++++++++++++++++------------------- src/yaml/cameraParser.hh | 2 +- src/yaml/objectParser.cc | 29 ++++++++++++++++++----------- src/yaml/sceneParser.cc | 4 ++-- src/yaml/vectorParser.cc | 16 ++++++---------- src/yaml/vectorParser.hh | 15 ++++++++------- 11 files changed, 79 insertions(+), 66 deletions(-) diff --git a/src/lightPoint.cc b/src/lightPoint.cc index dd52a3c..2a1021a 100644 --- a/src/lightPoint.cc +++ b/src/lightPoint.cc @@ -6,6 +6,7 @@ #include "lightPoint.hh" +using charles::basics::Color; using charles::basics::Vector4; @@ -19,7 +20,7 @@ PointLight::PointLight(const Vector4& origin, { } -Vector4 +Vector4& PointLight::GetOrigin() { return mOrigin; diff --git a/src/object.cc b/src/object.cc index 3537d49..c3f6bce 100644 --- a/src/object.cc +++ b/src/object.cc @@ -11,7 +11,7 @@ #include "object.hh" -#include "material.h" +#include "material.hh" #include "basics/basics.hh" diff --git a/src/reader_yaml.cc b/src/reader_yaml.cc index 4df4f32..a7924f8 100644 --- a/src/reader_yaml.cc +++ b/src/reader_yaml.cc @@ -58,6 +58,7 @@ private: }; #endif +namespace charles { ssize_t YAMLReader::read_file(const std::string& filename) @@ -152,3 +153,5 @@ error: yaml_parser_delete(&parser); return success; } + +} /* namespace charles */ \ No newline at end of file diff --git a/src/scene.cc b/src/scene.cc index 49d1aea..a48ec14 100644 --- a/src/scene.cc +++ b/src/scene.cc @@ -12,7 +12,6 @@ #include "scene.hh" -#include "basics.h" #include "light.hh" #include "log.hh" #include "object.hh" @@ -39,7 +38,7 @@ Scene::Scene() mCamera(new PerspectiveCamera()), mMaxDepth(5), mMinWeight(1e-6), - mAmbient(), + mAmbient(Color(1, 1, 1), 0.2), mObjects(), mLights(), mStats(), @@ -285,7 +284,7 @@ Scene::TraceRay(const Ray &ray, Ray shadowRay; for (PointLight *l : mLights) { - lightDirection = (l->GetOrigin() - intersection).normalize(); + lightDirection = basics::Normalized(l->GetOrigin() - intersection); ldotn = lightDirection.Dot(normal); /* @@ -319,7 +318,7 @@ Scene::TraceRay(const Ray &ray, /* * Compute basic Lambert diffuse shading for this object. */ - outColor += shapeColor * ( ambientLevel * mAmbient.compute_color_contribution() + outColor += shapeColor * ( ambientLevel * mAmbient.Contribution() + diffuseLevel * ldotn); } diff --git a/src/writer_png.cc b/src/writer_png.cc index 3001159..6a04187 100644 --- a/src/writer_png.cc +++ b/src/writer_png.cc @@ -9,18 +9,24 @@ #include #include -#include "scene.h" +#include "scene.hh" #include "writer_png.h" +#include "basics/basics.hh" extern "C" { #include } +using charles::basics::Color; + + static void png_user_error(png_structp png, png_const_charp msg); static void png_user_warning(png_structp png, png_const_charp msg); +namespace charles { + /* * PNGWriter::write_scene -- * @@ -29,7 +35,7 @@ static void png_user_warning(png_structp png, png_const_charp msg); int PNGWriter::write_scene(const Scene &scene, const std::string &filename) { - if (!scene.is_rendered()) { + if (!scene.IsRendered()) { return -1; } @@ -62,7 +68,7 @@ PNGWriter::write_scene(const Scene &scene, const std::string &filename) * - No compression */ png_set_IHDR(png, png_info, - scene.get_width(), scene.get_height(), + scene.GetWidth(), scene.GetHeight(), 8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE, PNG_COMPRESSION_TYPE_DEFAULT, @@ -75,21 +81,20 @@ PNGWriter::write_scene(const Scene &scene, const std::string &filename) png_write_info(png, png_info); // Write it! - const Color *pixels = scene.get_pixels(); + const Color* pixels = scene.GetPixels(); png_byte *row = NULL; int nbytes = 0; - for (int y = 0; y < scene.get_height(); y++) { - row = new png_byte[scene.get_width() * 3]; + for (UInt y = 0; y < scene.GetHeight(); y++) { + row = new png_byte[scene.GetWidth() * 3]; if (row == NULL) { // TODO: DANGER! WILL ROBINSON! } - for (int x = 0; x < scene.get_width(); x++) { - Color c = pixels[y * scene.get_width() + x]; + for (UInt x = 0; x < scene.GetWidth(); x++) { + Color c = pixels[y * scene.GetWidth() + x]; row[x*3+0] = 0xff * c.red; row[x*3+1] = 0xff * c.green; row[x*3+2] = 0xff * c.blue; nbytes += 3; - } png_write_row(png, row); delete[] row; @@ -103,6 +108,8 @@ PNGWriter::write_scene(const Scene &scene, const std::string &filename) return nbytes; } +} /* namespace charles */ + #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wunused-parameter" @@ -130,4 +137,4 @@ png_user_warning(png_structp png, png_const_charp msg) { } -#pragma clang diagnostic pop +#pragma clang diagnostic pop \ No newline at end of file diff --git a/src/yaml/cameraParser.cc b/src/yaml/cameraParser.cc index 34e8328..2db4cdc 100644 --- a/src/yaml/cameraParser.cc +++ b/src/yaml/cameraParser.cc @@ -10,6 +10,9 @@ #include "yaml/vectorParser.hh" +using charles::basics::Vector4; + + namespace charles { namespace yaml { @@ -87,13 +90,13 @@ CameraParser::HandleDirectionEvent(yaml_event_t& event) return; } - auto onDone = [this](Vector3 origin) { - mCamera->set_direction(origin); + auto onDone = [this](Vector4 direction) { + mCamera->SetDirection(direction); mSection = NoSection; SetShouldExpectKey(true); }; - GetParsers().push(new Vector3Parser(GetScene(), GetParsers(), onDone)); + GetParsers().push(new Vector4Parser(GetScene(), GetParsers(), onDone)); } @@ -106,13 +109,13 @@ CameraParser::HandleLookAtEvent(yaml_event_t& event) return; } - auto onDone = [this](Vector3 lookAt) { + auto onDone = [this](Vector4 lookAt) { mCamera->LookAt(lookAt); mSection = NoSection; SetShouldExpectKey(true); }; - GetParsers().push(new Vector3Parser(GetScene(), GetParsers(), onDone)); + GetParsers().push(new Vector4Parser(GetScene(), GetParsers(), onDone)); } @@ -125,13 +128,13 @@ CameraParser::HandleOriginEvent(yaml_event_t& event) return; } - auto onDone = [this](Vector3 origin) { + auto onDone = [this](Vector4 origin) { mCamera->SetOrigin(origin); mSection = NoSection; SetShouldExpectKey(true); }; - GetParsers().push(new Vector3Parser(GetScene(), GetParsers(), onDone)); + GetParsers().push(new Vector4Parser(GetScene(), GetParsers(), onDone)); } @@ -144,13 +147,13 @@ CameraParser::HandleRightEvent(yaml_event_t& event) return; } - auto onDone = [this](Vector3 right) { + auto onDone = [this](Vector4 right) { mCamera->SetRight(right); mSection = NoSection; SetShouldExpectKey(true); }; - GetParsers().push(new Vector3Parser(GetScene(), GetParsers(), onDone)); + GetParsers().push(new Vector4Parser(GetScene(), GetParsers(), onDone)); } @@ -166,18 +169,14 @@ CameraParser::HandleTypeEvent(yaml_event_t& event) event.data.scalar.length); if (value == "perspective") { if (mType == TypeOrthographic) { - Camera *newCamera = new PerspectiveCamera(*mCamera); - delete mCamera; - mCamera = newCamera; - GetScene().SetCamera(newCamera); + mCamera.reset(new PerspectiveCamera(*mCamera)); + GetScene().SetCamera(mCamera); } } else if (value == "orthographic") { if (mType == TypePerspective) { - Camera *newCamera = new OrthographicCamera(*mCamera); - delete mCamera; - mCamera = newCamera; - GetScene().SetCamera(newCamera); + mCamera.reset(new OrthographicCamera(*mCamera)); + GetScene().SetCamera(mCamera); } } else { @@ -198,13 +197,13 @@ CameraParser::HandleUpEvent(yaml_event_t& event) return; } - auto onDone = [this](Vector3 origin) { + auto onDone = [this](Vector4 origin) { mCamera->SetUp(origin); mSection = NoSection; SetShouldExpectKey(true); }; - GetParsers().push(new Vector3Parser(GetScene(), GetParsers(), onDone)); + GetParsers().push(new Vector4Parser(GetScene(), GetParsers(), onDone)); } } /* namespace yaml */ diff --git a/src/yaml/cameraParser.hh b/src/yaml/cameraParser.hh index 2578da0..13223ff 100644 --- a/src/yaml/cameraParser.hh +++ b/src/yaml/cameraParser.hh @@ -48,7 +48,7 @@ private: void HandleTypeEvent(yaml_event_t& event); void HandleUpEvent(yaml_event_t& event); - Camera *mCamera; + Camera::Ptr mCamera; Section mSection; Type mType; }; diff --git a/src/yaml/objectParser.cc b/src/yaml/objectParser.cc index eba3e6e..614a9d5 100644 --- a/src/yaml/objectParser.cc +++ b/src/yaml/objectParser.cc @@ -10,8 +10,8 @@ #include #include -#include "material.h" -#include "object.h" +#include "material.hh" +#include "object.hh" #include "objectBox.hh" #include "objectPlane.hh" #include "objectSphere.hh" @@ -19,6 +19,10 @@ #include "yaml/vectorParser.hh" +using charles::basics::Color; +using charles::basics::Vector4; + + namespace charles { namespace yaml { @@ -41,7 +45,7 @@ ObjectParser::ObjectParser(Scene& scene, } else { assert(false); } - GetScene().add_shape(mObject); + GetScene().AddObject(mObject); } @@ -169,13 +173,16 @@ ObjectParser::HandleOriginEvent(yaml_event_t& event) return; } - auto onDone = [this](Vector3 origin) { + auto onDone = [this](Vector4 origin) { + /* TODO: Once Place() and Move() are implemented on Object, use that. */ +#if 0 mObject->SetOrigin(origin); mSection = NoSection; SetShouldExpectKey(true); +#endif }; - GetParsers().push(new Vector3Parser(GetScene(), GetParsers(), onDone)); + GetParsers().push(new Vector4Parser(GetScene(), GetParsers(), onDone)); } @@ -209,13 +216,13 @@ ObjectParser::HandleNearEvent(yaml_event_t& event) return; } - auto onDone = [this](Vector3 near) { + auto onDone = [this](Vector4 near) { std::dynamic_pointer_cast(mObject)->SetNear(near); mSection = NoSection; SetShouldExpectKey(true); }; - GetParsers().push(new Vector3Parser(GetScene(), GetParsers(), onDone)); + GetParsers().push(new Vector4Parser(GetScene(), GetParsers(), onDone)); } @@ -228,13 +235,13 @@ ObjectParser::HandleFarEvent(yaml_event_t& event) return; } - auto onDone = [this](Vector3 far) { + auto onDone = [this](Vector4 far) { std::dynamic_pointer_cast(mObject)->SetFar(far); mSection = NoSection; SetShouldExpectKey(true); }; - GetParsers().push(new Vector3Parser(GetScene(), GetParsers(), onDone)); + GetParsers().push(new Vector4Parser(GetScene(), GetParsers(), onDone)); } @@ -247,13 +254,13 @@ ObjectParser::HandleNormalEvent(yaml_event_t& event) return; } - auto onDone = [this](Vector3 normal) { + auto onDone = [this](Vector4 normal) { std::dynamic_pointer_cast(mObject)->SetNormal(normal); mSection = NoSection; SetShouldExpectKey(true); }; - GetParsers().push(new Vector3Parser(GetScene(), GetParsers(), onDone)); + GetParsers().push(new Vector4Parser(GetScene(), GetParsers(), onDone)); } diff --git a/src/yaml/sceneParser.cc b/src/yaml/sceneParser.cc index 6b99230..e206cc6 100644 --- a/src/yaml/sceneParser.cc +++ b/src/yaml/sceneParser.cc @@ -96,8 +96,8 @@ SceneParser::HandleDimensionsEvent(yaml_event_t& event) } Scene& sc = GetScene(); - sc.set_width(dimensions.at(0)); - sc.set_height(dimensions.at(1)); + sc.SetWidth(dimensions.at(0)); + sc.SetHeight(dimensions.at(1)); mSection = NoSection; SetShouldExpectKey(true); diff --git a/src/yaml/vectorParser.cc b/src/yaml/vectorParser.cc index 3a33577..3283fdf 100644 --- a/src/yaml/vectorParser.cc +++ b/src/yaml/vectorParser.cc @@ -8,10 +8,14 @@ #include "yaml/vectorParser.hh" +using charles::basics::Color; +using charles::basics::Vector4; + + namespace charles { namespace yaml { -Vector3Parser::Vector3Parser(Scene& scene, +Vector4Parser::Vector4Parser(Scene& scene, ParserStack& parsers, CallbackFunction onDone) : ScalarSequenceParser(scene, parsers) @@ -21,16 +25,12 @@ Vector3Parser::Vector3Parser(Scene& scene, assert(seq.size() != 3); return; } - onDone(Vector3(seq[0], seq[1], seq[2])); + onDone(Vector4(seq[0], seq[1], seq[2])); }; SetCallback(onSeqDone); } -Vector3Parser::~Vector3Parser() -{ } - - ColorParser::ColorParser(Scene& scene, ParserStack& parsers, CallbackFunction onDone) @@ -51,9 +51,5 @@ ColorParser::ColorParser(Scene& scene, SetCallback(onSeqDone); } - -ColorParser::~ColorParser() -{ } - } /* namespace yaml */ } /* namespace charles */ diff --git a/src/yaml/vectorParser.hh b/src/yaml/vectorParser.hh index 4e5374e..8c237b8 100644 --- a/src/yaml/vectorParser.hh +++ b/src/yaml/vectorParser.hh @@ -14,6 +14,7 @@ #include #include "parsers.hh" +#include "basics/basics.hh" namespace charles { @@ -83,20 +84,20 @@ private: }; -struct Vector3Parser - : ScalarSequenceParser +struct Vector4Parser + : ScalarSequenceParser { - typedef std::function CallbackFunction; + typedef std::function CallbackFunction; - Vector3Parser(Scene& scene, ParserStack& parsers, CallbackFunction onDone); - ~Vector3Parser(); + Vector4Parser(Scene& scene, ParserStack& parsers, CallbackFunction onDone); + ~Vector4Parser(); }; struct ColorParser - : ScalarSequenceParser + : ScalarSequenceParser { - typedef std::function CallbackFunction; + typedef std::function CallbackFunction; ColorParser(Scene& scene, ParserStack& parsers, CallbackFunction onDone); ~ColorParser(); From c90c545f402d2fbfb548b684b8f9763e569235e6 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 21:30:28 -0700 Subject: [PATCH 63/92] Define color constants --- src/basics/color.cc | 7 +++++++ src/basics/color.hh | 4 ++++ 2 files changed, 11 insertions(+) diff --git a/src/basics/color.cc b/src/basics/color.cc index f9db9cd..3c75aaf 100644 --- a/src/basics/color.cc +++ b/src/basics/color.cc @@ -13,6 +13,13 @@ namespace charles { namespace basics { +const Color Color::Black = Color(); +const Color Color::White = Color(1, 1, 1); +const Color Color::Red = Color(1, 0, 0); +const Color Color::Green = Color(0, 1, 0); +const Color Color::Blue = Color(0, 0, 1); + + /* * charles::basics::Color::Color -- */ diff --git a/src/basics/color.hh b/src/basics/color.hh index ed4d0c2..b2624b1 100644 --- a/src/basics/color.hh +++ b/src/basics/color.hh @@ -3,6 +3,9 @@ * Eryn Wells */ +#ifndef __BASICS_COLOR_HH__ +#define __BASICS_COLOR_HH__ + #include "basics/types.hh" @@ -52,3 +55,4 @@ std::ostream &operator<<(std::ostream &os, const Color &c); } /* namespace basics */ } /* namespace charles */ +#endif /* __BASICS_COLOR_HH__ */ From 505a77d0e2722ad67d00aa75b72e660ce3bf100d Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 22:00:23 -0700 Subject: [PATCH 64/92] LOG_TRACE YAML events --- src/reader_yaml.cc | 76 ++++++++++++++++++++++++---------------------- 1 file changed, 39 insertions(+), 37 deletions(-) diff --git a/src/reader_yaml.cc b/src/reader_yaml.cc index a7924f8..d376024 100644 --- a/src/reader_yaml.cc +++ b/src/reader_yaml.cc @@ -14,11 +14,15 @@ #include "yaml.h" #include "charles.hh" +#include "log.hh" #include "reader_yaml.hh" #include "yaml/parsers.hh" #include "yaml/sceneParser.hh" +#define LOG_NAME "yaml" +#include "logModule.hh" + #if 0 struct ObjectParser @@ -87,47 +91,45 @@ YAMLReader::read_file(const std::string& filename) goto error; } - if (verbosity >= 4) { - switch (event.type) { - case YAML_NO_EVENT: - printf("YAML_NO_EVENT\n"); - break; + switch (event.type) { + case YAML_NO_EVENT: + LOG_TRACE << "YAML_NO_EVENT"; + break; - case YAML_STREAM_START_EVENT: - printf("YAML_STREAM_START_EVENT\n"); - break; - case YAML_STREAM_END_EVENT: - printf("YAML_STREAM_END_EVENT\n"); - break; + case YAML_STREAM_START_EVENT: + LOG_TRACE << "YAML_STREAM_START_EVENT"; + break; + case YAML_STREAM_END_EVENT: + LOG_TRACE << "YAML_STREAM_END_EVENT"; + break; - case YAML_DOCUMENT_START_EVENT: - printf("YAML_DOCUMENT_START_EVENT\n"); - break; - case YAML_DOCUMENT_END_EVENT: - printf("YAML_DOCUMENT_END_EVENT\n"); - break; + case YAML_DOCUMENT_START_EVENT: + LOG_TRACE << "YAML_DOCUMENT_START_EVENT"; + break; + case YAML_DOCUMENT_END_EVENT: + LOG_TRACE << "YAML_DOCUMENT_END_EVENT"; + break; - case YAML_ALIAS_EVENT: - printf("YAML_ALIAS_EVENT\n"); - break; - case YAML_SCALAR_EVENT: - printf("YAML_SCALAR_EVENT\n"); - break; + case YAML_ALIAS_EVENT: + LOG_TRACE << "YAML_ALIAS_EVENT"; + break; + case YAML_SCALAR_EVENT: + LOG_TRACE << "YAML_SCALAR_EVENT"; + break; - case YAML_SEQUENCE_START_EVENT: - printf("YAML_SEQUENCE_START_EVENT\n"); - break; - case YAML_SEQUENCE_END_EVENT: - printf("YAML_SEQUENCE_END_EVENT\n"); - break; + case YAML_SEQUENCE_START_EVENT: + LOG_TRACE << "YAML_SEQUENCE_START_EVENT"; + break; + case YAML_SEQUENCE_END_EVENT: + LOG_TRACE << "YAML_SEQUENCE_END_EVENT"; + break; - case YAML_MAPPING_START_EVENT: - printf("YAML_MAPPING_START_EVENT\n"); - break; - case YAML_MAPPING_END_EVENT: - printf("YAML_MAPPING_END_EVENT\n"); - break; - } + case YAML_MAPPING_START_EVENT: + LOG_TRACE << "YAML_MAPPING_START_EVENT"; + break; + case YAML_MAPPING_END_EVENT: + LOG_TRACE << "YAML_MAPPING_END_EVENT"; + break; } if (event.type == YAML_DOCUMENT_START_EVENT) { @@ -154,4 +156,4 @@ error: return success; } -} /* namespace charles */ \ No newline at end of file +} /* namespace charles */ From 1f01de6393574c966777fafd040361059408f26a Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 22:00:43 -0700 Subject: [PATCH 65/92] Remove VectorParser and ColorParser destructors They weren't being used. --- src/yaml/vectorParser.hh | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/yaml/vectorParser.hh b/src/yaml/vectorParser.hh index 8c237b8..2d66391 100644 --- a/src/yaml/vectorParser.hh +++ b/src/yaml/vectorParser.hh @@ -90,7 +90,6 @@ struct Vector4Parser typedef std::function CallbackFunction; Vector4Parser(Scene& scene, ParserStack& parsers, CallbackFunction onDone); - ~Vector4Parser(); }; @@ -100,7 +99,6 @@ struct ColorParser typedef std::function CallbackFunction; ColorParser(Scene& scene, ParserStack& parsers, CallbackFunction onDone); - ~ColorParser(); }; } /* namespace yaml */ From a5f451a1202c2fb3cf0666865d5804e1cb9decb4 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 9 Aug 2014 22:00:54 -0700 Subject: [PATCH 66/92] Basics unit tests found some bugs! --- src/basics/matrix.hh | 4 +- src/basics/vector.cc | 4 +- test/test_basics.cc | 132 ++++++++++++++++++++++--------------------- 3 files changed, 72 insertions(+), 68 deletions(-) diff --git a/src/basics/matrix.hh b/src/basics/matrix.hh index b1d751b..249f110 100644 --- a/src/basics/matrix.hh +++ b/src/basics/matrix.hh @@ -165,7 +165,7 @@ bool Matrix::operator==(const Matrix& rhs) const { - for (int i = 0; i < N*M; i++) { + for (UInt i = 0; i < N*M; i++) { /* TODO: Use NearlyEqual. */ if (mData[i] != rhs.mData[i]) { return false; @@ -254,7 +254,7 @@ Matrix::operator*(Matrix rhs) /* Each cell is Sigma(k=0, M)(lhs[ik] * rhs[kj]) */ result(i, j) = 0.0; for (UInt k = 0; k < M; k++) { - result(i, j) += mData[i*N + k] * rhs(k*P, j); + result(i, j) += mData[i*N + k] * rhs(k, j); } } } diff --git a/src/basics/vector.cc b/src/basics/vector.cc index 815196c..7a8c7e1 100644 --- a/src/basics/vector.cc +++ b/src/basics/vector.cc @@ -93,7 +93,7 @@ Vector4 Vector4::operator*(const Double& rhs) const { - return static_cast(*this * rhs); + return static_cast>(*this) * rhs; } @@ -182,7 +182,7 @@ Double Vector4::Dot(const Vector4& rhs) const { - return mData[0] * rhs.mData[0] + mData[1] * rhs.mData[1] + mData[2] + rhs.mData[2]; + return mData[0] * rhs.mData[0] + mData[1] * rhs.mData[1] + mData[2] * rhs.mData[2]; } diff --git a/test/test_basics.cc b/test/test_basics.cc index 374a668..c5fa019 100644 --- a/test/test_basics.cc +++ b/test/test_basics.cc @@ -7,160 +7,164 @@ #include "gtest/gtest.h" -#include "basics.h" +#include "basics/basics.hh" -class Vector3Test +using charles::basics::Vector4; +using charles::basics::Matrix4; + + +class Vector4Test : public ::testing::Test { public: virtual void SetUp(); protected: - Vector3 v1, v2; + Vector4 v1, v2; }; void -Vector3Test::SetUp() +Vector4Test::SetUp() { - v1 = Vector3(1, 3, 5); - v2 = Vector3(7, 13, 17); + v1 = Vector4(1, 3, 5); + v2 = Vector4(7, 13, 17); } -TEST_F(Vector3Test, OperatorEq) +TEST_F(Vector4Test, OperatorEq) { v1 = v2; EXPECT_EQ(v2, v1); } -TEST_F(Vector3Test, OperatorMul) +TEST_F(Vector4Test, OperatorMul) { - Vector3 out; + Vector4 out; out = v1 * 5; - EXPECT_EQ(5, out.x); - EXPECT_EQ(15, out.y); - EXPECT_EQ(25, out.z); + EXPECT_EQ(5, out.X()); + EXPECT_EQ(15, out.Y()); + EXPECT_EQ(25, out.Z()); out = v1 * -7; - EXPECT_EQ(-7, out.x); - EXPECT_EQ(-21, out.y); - EXPECT_EQ(-35, out.z); + EXPECT_EQ(-7, out.X()); + EXPECT_EQ(-21, out.Y()); + EXPECT_EQ(-35, out.Z()); out = v1; out *= 5; - EXPECT_EQ(5, out.x); - EXPECT_EQ(15, out.y); - EXPECT_EQ(25, out.z); + EXPECT_EQ(5, out.X()); + EXPECT_EQ(15, out.Y()); + EXPECT_EQ(25, out.Z()); out = v1; out *= -7; - EXPECT_EQ(-7, out.x); - EXPECT_EQ(-21, out.y); - EXPECT_EQ(-35, out.z); + EXPECT_EQ(-7, out.X()); + EXPECT_EQ(-21, out.Y()); + EXPECT_EQ(-35, out.Z()); } -TEST_F(Vector3Test, OperatorDiv) +TEST_F(Vector4Test, OperatorDiv) { - Vector3 out; + Vector4 out; out = v1 / 5.0; - EXPECT_FLOAT_EQ(1.0/5.0, out.x); - EXPECT_FLOAT_EQ(3.0/5.0, out.y); - EXPECT_FLOAT_EQ(5.0/5.0, out.z); + EXPECT_FLOAT_EQ(1.0/5.0, out.X()); + EXPECT_FLOAT_EQ(3.0/5.0, out.Y()); + EXPECT_FLOAT_EQ(5.0/5.0, out.Z()); out = v1 / -7.0; - EXPECT_FLOAT_EQ(1.0/-7.0, out.x); - EXPECT_FLOAT_EQ(3.0/-7.0, out.y); - EXPECT_FLOAT_EQ(5.0/-7.0, out.z); + EXPECT_FLOAT_EQ(1.0/-7.0, out.X()); + EXPECT_FLOAT_EQ(3.0/-7.0, out.Y()); + EXPECT_FLOAT_EQ(5.0/-7.0, out.Z()); out = v1; out /= 5.0; - EXPECT_FLOAT_EQ(1.0/5.0, out.x); - EXPECT_FLOAT_EQ(3.0/5.0, out.y); - EXPECT_FLOAT_EQ(5.0/5.0, out.z); + EXPECT_FLOAT_EQ(1.0/5.0, out.X()); + EXPECT_FLOAT_EQ(3.0/5.0, out.Y()); + EXPECT_FLOAT_EQ(5.0/5.0, out.Z()); out = v1; out /= -7.0; - EXPECT_FLOAT_EQ(1.0/-7.0, out.x); - EXPECT_FLOAT_EQ(3.0/-7.0, out.y); - EXPECT_FLOAT_EQ(5.0/-7.0, out.z); + EXPECT_FLOAT_EQ(1.0/-7.0, out.X()); + EXPECT_FLOAT_EQ(3.0/-7.0, out.Y()); + EXPECT_FLOAT_EQ(5.0/-7.0, out.Z()); } -TEST_F(Vector3Test, OperatorAdd) +TEST_F(Vector4Test, OperatorAdd) { - Vector3 out; + Vector4 out; out = v1 + v2; - EXPECT_EQ(8, out.x); - EXPECT_EQ(16, out.y); - EXPECT_EQ(22, out.z); + EXPECT_EQ(8, out.X()); + EXPECT_EQ(16, out.Y()); + EXPECT_EQ(22, out.Z()); out = v1; out += v2; - EXPECT_EQ(8, out.x); - EXPECT_EQ(16, out.y); - EXPECT_EQ(22, out.z); + EXPECT_EQ(8, out.X()); + EXPECT_EQ(16, out.Y()); + EXPECT_EQ(22, out.Z()); } -TEST_F(Vector3Test, OperatorSub) +TEST_F(Vector4Test, OperatorSub) { - Vector3 out; + Vector4 out; out = v1 - v2; - EXPECT_EQ(-6, out.x); - EXPECT_EQ(-10, out.y); - EXPECT_EQ(-12, out.z); + EXPECT_EQ(-6, out.X()); + EXPECT_EQ(-10, out.Y()); + EXPECT_EQ(-12, out.Z()); out = v2 - v1; - EXPECT_EQ(6, out.x); - EXPECT_EQ(10, out.y); - EXPECT_EQ(12, out.z); + EXPECT_EQ(6, out.X()); + EXPECT_EQ(10, out.Y()); + EXPECT_EQ(12, out.Z()); v1 -= v2; - EXPECT_EQ(-6, v1.x); - EXPECT_EQ(-10, v1.y); - EXPECT_EQ(-12, v1.z); + EXPECT_EQ(-6, v1.X()); + EXPECT_EQ(-10, v1.Y()); + EXPECT_EQ(-12, v1.Z()); } -TEST_F(Vector3Test, OperatorBoolEq) +TEST_F(Vector4Test, OperatorBoolEq) { EXPECT_EQ(v1, v1); EXPECT_EQ(v2, v2); } -TEST_F(Vector3Test, OperatorBoolNe) +TEST_F(Vector4Test, OperatorBoolNe) { EXPECT_NE(v1, v2); EXPECT_NE(v2, v1); } -TEST_F(Vector3Test, Length2) +TEST_F(Vector4Test, Length2) { - EXPECT_EQ(35.0, v1.length2()); - EXPECT_EQ(507.0, v2.length2()); + EXPECT_EQ(35.0, v1.Length2()); + EXPECT_EQ(507.0, v2.Length2()); } -TEST_F(Vector3Test, Length) +TEST_F(Vector4Test, Length) { - EXPECT_FLOAT_EQ(5.916079783099616, v1.length()); - EXPECT_FLOAT_EQ(22.5166604983954, v2.length()); + EXPECT_FLOAT_EQ(5.916079783099616, v1.Length()); + EXPECT_FLOAT_EQ(22.5166604983954, v2.Length()); } -TEST_F(Vector3Test, DotProduct) +TEST_F(Vector4Test, DotProduct) { - EXPECT_EQ(131.0, v1.dot(v2)); + EXPECT_EQ(131.0, v1.Dot(v2)); } #pragma mark Matrix4 Tests From 96f782c4ac062b049fca6729d79ee0f7dc411845 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sun, 10 Aug 2014 09:41:48 -0700 Subject: [PATCH 67/92] Add tests for matrix multiplication By identity matrix With vectors --- test/test_basics.cc | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-) diff --git a/test/test_basics.cc b/test/test_basics.cc index c5fa019..98c7d71 100644 --- a/test/test_basics.cc +++ b/test/test_basics.cc @@ -177,6 +177,7 @@ public: protected: Matrix4 m1, m2; + Matrix4 id; }; @@ -194,6 +195,8 @@ Matrix4Test::SetUp() 34, 55, 89, 144, 233, 377, 610, 987}; m2 = Matrix4(m2Cells); + + id = Matrix4::Identity(); } @@ -245,7 +248,7 @@ TEST_F(Matrix4Test, ScalarMultiplication) } -TEST_F(Matrix4Test, MatrixMultiplication) +TEST_F(Matrix4Test, SquareMatrixMultiplication) { const Double p1Expect[] = {1045, 1690, 2735, 4425, 2137, 3454, 5591, 9045, @@ -275,3 +278,28 @@ TEST_F(Matrix4Test, MatrixMultiplication) EXPECT_EQ(p4.CArray()[i], m1.CArray()[i]); } } + + +TEST_F(Matrix4Test, IdentityMultiplication) +{ + Matrix4 p1 = m1 * id; + for (UInt i = 0; i < 16; i++) { + EXPECT_EQ(p1.CArray()[i], m1.CArray()[i]); + } + + Matrix4 p2 = id * m1; + for (UInt i = 0; i < 16; i++) { + EXPECT_EQ(p2.CArray()[i], m1.CArray()[i]); + } +} + + +TEST_F(Matrix4Test, VectorMultiplication) +{ + Vector4 v1(1, 2, 3); + + Vector4 p1 = id * v1; + EXPECT_EQ(p1.X(), v1.X()); + EXPECT_EQ(p1.Y(), v1.Y()); + EXPECT_EQ(p1.Z(), v1.Z()); +} From 74bbc876107e0571b6737378a6d80e6976ce6c3a Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sun, 10 Aug 2014 09:42:02 -0700 Subject: [PATCH 68/92] Trying to get this copy/move thing right between matrices and vectors --- src/basics/vector.cc | 9 ++++++--- src/basics/vector.hh | 4 +++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/basics/vector.cc b/src/basics/vector.cc index 7a8c7e1..7d42a59 100644 --- a/src/basics/vector.cc +++ b/src/basics/vector.cc @@ -25,9 +25,10 @@ Vector4::Vector4(const Double& x, } -Vector4::Vector4(const Matrix<4,1>&& rhs) - : Vector4(static_cast(rhs)) -{ } +Vector4::Vector4(const Matrix<4,1>& rhs) +{ + memcpy(mData, rhs.CArray(), sizeof(Double) * 4); +} /* @@ -86,6 +87,7 @@ Vector4::Z() } +#if 0 /* * charles::basics::Vector4::operator* -- */ @@ -95,6 +97,7 @@ Vector4::operator*(const Double& rhs) { return static_cast>(*this) * rhs; } +#endif /* diff --git a/src/basics/vector.hh b/src/basics/vector.hh index e5ce24c..787bb4f 100644 --- a/src/basics/vector.hh +++ b/src/basics/vector.hh @@ -25,7 +25,7 @@ struct Vector4 : public Vector<4> { Vector4(const Double& x = 0.0, const Double& y = 0.0, const Double& z = 0.0); - Vector4(const Matrix<4,1>&& m); + Vector4(const Matrix<4,1>& m); Double& X(); const Double& X() const; @@ -34,7 +34,9 @@ struct Vector4 Double& Z(); const Double& Z() const; +#if 0 Vector4 operator*(const Double& rhs) const; +#endif Vector4 operator+(const Vector4& rhs) const; Vector4& operator+=(const Vector4& rhs); From 990d2b4c1161137c49d3b48be9dbe27a665dc178 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sun, 10 Aug 2014 10:48:54 -0700 Subject: [PATCH 69/92] Add basics/util.hh A place for NearZero, etc --- src/basics/util.hh | 61 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 src/basics/util.hh diff --git a/src/basics/util.hh b/src/basics/util.hh new file mode 100644 index 0000000..d65ff64 --- /dev/null +++ b/src/basics/util.hh @@ -0,0 +1,61 @@ +/* util.hh + * vim: set tw=80: + * Eryn Wells + */ + +#ifndef __BASICS_UTIL_HH__ +#define __BASICS_UTIL_HH__ + +#include + + +/** + * A very small constant. If a value is between EPSILON and 0.0, it is + * considered to be zero. + */ +const Double EPSILON = 1.0e-10; + + +/** + * The maximum distance a ray can travel. This is the maximum value t can be. + */ +const Double MAX_DISTANCE = 1.0e7; + + +/** + * Determine if the value is "close enough" to zero. Takes the absolute value + * and compares it to `EPSILON`. + * + * @see EPSILON + * + * @param [in] value The value to check + * @returns `true` if the value is close enough to zero + */ +template +inline bool +NearZero(T value) +{ + return std::fabs(value) < EPSILON; +} + + +/** + * Determine if two values are "close enough" to be considered equal. Subtracts + * one from the other and checks if the result is near zero. + * + * @see NearZero + * + * @param [in] left The left parameter + * @param [in] right The right parameter + * @returns `true` if the values are close enough to be equal + */ +template +inline bool +NearlyEqual(T left, + U right) +{ + return NearZero(left - right); +} + +#endif /* __BASICS_UTIL_HH__ */ + From 30d057001095af23d8728e1ce5fa7a6e951e93f7 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sun, 10 Aug 2014 10:49:45 -0700 Subject: [PATCH 70/92] Add TooFar to util.hh --- src/basics/basics.hh | 49 +------------------------------------------- src/basics/util.hh | 7 +++++++ 2 files changed, 8 insertions(+), 48 deletions(-) diff --git a/src/basics/basics.hh b/src/basics/basics.hh index d6b91e1..a3c8fe4 100644 --- a/src/basics/basics.hh +++ b/src/basics/basics.hh @@ -15,56 +15,9 @@ #include "basics/matrix.hh" #include "basics/ray.hh" #include "basics/types.hh" +#include "basics/util.hh" #include "basics/vector.hh" - -/** - * A very small constant. If a value is between EPSILON and 0.0, it is - * considered to be zero. - */ -const Double EPSILON = 1.0e-10; - -/** - * The maximum distance a ray can travel. This is the maximum value t can be. - */ -const Double MAX_DISTANCE = 1.0e7; - -/** - * Determine if the value is "close enough" to zero. Takes the absolute value - * and compares it to `EPSILON`. - * - * @see EPSILON - * - * @param [in] value The value to check - * @returns `true` if the value is close enough to zero - */ -template -inline bool -NearZero(const T value) -{ - return std::fabs(value) < EPSILON; -} - - -/** - * Determine if two values are "close enough" to be considered equal. Subtracts - * one from the other and checks if the result is near zero. - * - * @see NearZero - * - * @param [in] left The left parameter - * @param [in] right The right parameter - * @returns `true` if the values are close enough to be equal - */ -template -inline bool -NearlyEqual(const T left, - const T right) -{ - return NearZero(left - right); -} - - inline bool TooFar(const Double& value) { diff --git a/src/basics/util.hh b/src/basics/util.hh index d65ff64..2c36c0f 100644 --- a/src/basics/util.hh +++ b/src/basics/util.hh @@ -57,5 +57,12 @@ NearlyEqual(T left, return NearZero(left - right); } + +inline bool +TooFar(const Double& value) +{ + return value > MAX_DISTANCE; +} + #endif /* __BASICS_UTIL_HH__ */ From 49d097a80342e4739fef983bf58c7877a2f9f8b8 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sun, 10 Aug 2014 10:51:12 -0700 Subject: [PATCH 71/92] Get rid of Matrix, just use Matrix4 --- src/basics/basics.hh | 6 - src/basics/matrix.cc | 232 +++++++++++++++++++++++++++++++-- src/basics/matrix.hh | 297 +++++++------------------------------------ src/basics/vector.cc | 122 ++++++++++++------ src/basics/vector.hh | 73 +++++++---- src/object.cc | 2 +- 6 files changed, 399 insertions(+), 333 deletions(-) diff --git a/src/basics/basics.hh b/src/basics/basics.hh index a3c8fe4..bedc145 100644 --- a/src/basics/basics.hh +++ b/src/basics/basics.hh @@ -18,10 +18,4 @@ #include "basics/util.hh" #include "basics/vector.hh" -inline bool -TooFar(const Double& value) -{ - return value > MAX_DISTANCE; -} - #endif /* __BASICS_BASICS_HH__ */ diff --git a/src/basics/matrix.cc b/src/basics/matrix.cc index 23b28ba..5a3798b 100644 --- a/src/basics/matrix.cc +++ b/src/basics/matrix.cc @@ -3,27 +3,243 @@ * Eryn Wells */ -#include "matrix.hh" +#include +#include +#include + +#include "basics/matrix.hh" + +#include "basics/util.hh" namespace charles { namespace basics { +#pragma mark Static Methods + +/* + * charles::basics::Matrix4::Zero -- + */ +/* static */ Matrix4 +Matrix4::Zero() +{ + Matrix4 m; + bzero(m.mData, sizeof(Double) * 16); + return m; +} + + +/* + * charles::basics::Matrix4::Identity -- + */ +/* static */ Matrix4 +Matrix4::Identity() +{ + auto m = Matrix4::Zero(); + for (size_t i = 0; i < 4; i++) { + m(i,i) = 1.0; + } + return m; +} + + /* * charles::basics::TranslationMatrix -- */ -Matrix4 -TranslationMatrix(const Double& x, - const Double& y, - const Double& z) +/* static */ Matrix4 +Translation(Double x, + Double y, + Double z) { Matrix4 m = Matrix4::Identity(); - m(0, 3) = x; - m(1, 3) = y; - m(2, 3) = z; + m(0,3) = x; + m(1,3) = y; + m(2,3) = z; return m; } +#pragma mark Constructors and Assignment + +/* + * charles::basics::Matrix4::Matrix4 -- + */ +Matrix4::Matrix4() + : mData() +{ } + + +/* + * charles::basics::Matrix4::Matrix4 -- + */ +Matrix4::Matrix4(const Double data[16]) +{ + memcpy(mData, data, sizeof(Double) * 16); +} + + +/* + * charles::basics::Matrix4::Matrix4 -- + */ +Matrix4::Matrix4(const Matrix4 &rhs) + : Matrix4(rhs.mData) +{ } + + +/* + * charles::basics::Matrix4::operator= -- + */ +Matrix4& +Matrix4::operator=(const Matrix4 &rhs) +{ + memcpy(mData, rhs.mData, sizeof(Double) * 16); + return *this; +} + +#pragma mark Boolean Operators + +/* + * charles::basics::Matrix4::operator== -- + */ +bool +Matrix4::operator==(const Matrix4 &rhs) + const +{ + for (int i = 0; i < 16; i++) { + if (!NearlyEqual(mData[i], rhs.mData[i])) { + return false; + } + } + return true; +} + + +/* + * charles::basics::Matrix4::operator!= -- + */ +bool +Matrix4::operator!=(const Matrix4 &rhs) + const +{ + return !(*this == rhs); +} + +#pragma mark Element Access + +/* + * charles::basics::Matrix4::operator() -- + */ +Double& +Matrix4::operator()(UInt i, UInt j) +{ + if (i >= 4 || j >= 4) { + std::stringstream ss; + ss << "matrix index out of bounds: i = " << i << ", j = " << j; + throw std::out_of_range(ss.str()); + } + return mData[i * 4 + j]; +} + + +/* + * charles::basics::Matrix4::operator() -- + */ +Double +Matrix4::operator()(UInt i, UInt j) + const +{ + return operator()(i, j); +} + + +/* + * charles::basics::Matrix4::CArray -- + */ +const Double* +Matrix4::CArray() + const +{ + return mData; +} + +#pragma mark Maths + +/* + * charles::basics::Matrix4::operator* -- + */ +Matrix4 +Matrix4::operator*(Double rhs) + const +{ + return Matrix4(*this) *= rhs; +} + + +/* + * charles::basics::Matrix4::operator/ -- + */ +Matrix4 +Matrix4::operator/(Double rhs) + const +{ + return Matrix4(*this) /= rhs; +} + + +/* + * charles::basics::Matrix4::operator*= -- + */ +Matrix4& +Matrix4::operator*=(Double rhs) +{ + for (UInt i = 0; i < 16; i++) { + mData[i] *= rhs; + } + return *this; +} + + +/* + * charles::basics::Matrix4::operator/= -- + */ +Matrix4& +Matrix4::operator/=(Double rhs) +{ + return *this *= (1.0 / rhs); +} + + +/* + * charles::basics::Matrix4::operator* -- + */ +Matrix4 +Matrix4::operator*(const Matrix4& rhs) + const +{ + Matrix4 result; + for (UInt i = 0; i < 4; i++) { + for (UInt j = 0; j < 4; j++) { + /* Each cell is Sigma(k=0, M)(lhs[ik] * rhs[kj]) */ + result(i,j) = 0.0; + for (UInt k = 0; k < 4; k++) { + result(i,j) += mData[i*4 + k] * rhs(k,j); + } + } + } + return result; +} + + +/* + * charles::basics::operator* -- + */ +Matrix4 +operator*(Double lhs, + const Matrix4& rhs) +{ + /* Scalar multiplication is commutative. */ + return rhs * lhs; +} + } /* namespace mespace */ } /* namespace charles */ diff --git a/src/basics/matrix.hh b/src/basics/matrix.hh index 249f110..c7224a9 100644 --- a/src/basics/matrix.hh +++ b/src/basics/matrix.hh @@ -16,274 +16,71 @@ namespace charles { namespace basics { -/** - * A generic, templated Matrix class taking two template parameters. `N` is the - * number of rows. `M` is the number of columns. If `M` is not specified, the - * matrix will be square. - */ -template -struct Matrix +struct Vector4; + + +/** A 4x4 matrix, used for 3D transforms. */ +struct Matrix4 { - /** Construct an N x M matrix of zeros. */ - static Matrix Zero(); + /** Create a 4x4 matrix of zeros. */ + static Matrix4 Zero(); + + /** Create a 4x4 identity matrix. */ + static Matrix4 Identity(); + + /** Create a 4x4 translation matrix. */ + static Matrix4 Translation(Double x, Double y, Double z); + + Matrix4(); + Matrix4(const Double *data); + Matrix4(const Matrix4 &rhs); + + Matrix4& operator=(const Matrix4 &rhs); + + bool operator==(const Matrix4 &rhs) const; + bool operator!=(const Matrix4 &rhs) const; /** - * Construct an N x M identity matrix. Identity matrices are always square. - * It is a (compile time) error to call Identity on a Matrix class where - * N != M. + * Get the ij'th item. In debug builds, this will assert if i or j are + * outside the bounds of the array. */ - static Matrix Identity(); - - Matrix(); - Matrix(const Double data[N*M]); - Matrix(const Matrix& rhs); - - Matrix& operator=(const Matrix& rhs); - - bool operator==(const Matrix& rhs) const; - bool operator!=(const Matrix& rhs) const; - - /** Value accessor. Get the ij'th item. */ Double& operator()(UInt i, UInt j); + Double operator()(UInt i, UInt j) const; + + /** Get the underlying C array */ + const Double *CArray() const; + + /* + * TODO: For completeness, matrix addition and subtraction, though I have + * yet to find a need for them... + */ /** * @defgroup Scalar multiplication * @{ */ - Matrix operator*(const Double& rhs) const; - Matrix& operator*=(const Double& rhs); - Matrix operator/(const Double& rhs) const; - Matrix& operator/=(const Double& rhs); + Matrix4 operator*(Double rhs) const; + Matrix4 operator/(Double rhs) const; + Matrix4& operator*=(Double rhs); + Matrix4& operator/=(Double rhs); /** @} */ - /** Matrix multiplication */ - template - Matrix operator*(Matrix rhs) const; - - /** Get the underlying C array */ - const Double* CArray() const; + /** + * @defgroup Matrix multiplication + * @{ + */ + Matrix4 operator*(const Matrix4 &rhs) const; + Vector4 operator*(const Vector4 &rhs) const; + /** @} */ protected: - /** The matrix data, stored in row-major format. */ - Double mData[N * M]; + /** The matrix data */ + Double mData[16]; }; /** Scalar multiplication, scalar factor on the left. */ -template -Matrix operator*(const Double& lhs, const Matrix& rhs); - - -/** A standard 4x4 matrix. */ -typedef Matrix<4> Matrix4; - - -/** - * Create a translation matrix that will translate a vector to the given - * coordinates. - */ -Matrix4 TranslationMatrix(const Double& x, const Double& y, const Double& z); - -#pragma mark Static Methods - -/* - * charles::basics::Matrix<>::Zero -- - */ -template -/* static */ Matrix -Matrix::Zero() -{ - Matrix m; - bzero(m.mData, sizeof(Double) * N * M); - return m; -} - - -/* - * charles::basics::Matrix<>::Identity -- - */ -template -/* static */ Matrix -Matrix::Identity() -{ - static_assert(N == M, "Identity matrices must be square."); - - auto m = Matrix::Zero(); - for (size_t i = 0; i < N; i++) { - m(i,i) = 1.0; - } - return m; -} - -#pragma mark Instance Methods - -/* - * charles::basics::Matrix<>::Matrix -- - */ -template -Matrix::Matrix() - : mData() -{ } - - -/* - * charles::basics::Matrix<>::Matrix -- - */ -template -Matrix::Matrix(const Double data[N*M]) -{ - memcpy(mData, data, sizeof(Double) * N * M); -} - - -/* - * charles::basics::Matrix<>::Matrix -- - */ -template -Matrix::Matrix(const Matrix& rhs) - : Matrix(rhs.mData) -{ } - - -/* - * charles::basics::Matrix<>::operator= -- - */ -template -Matrix& -Matrix::operator=(const Matrix& rhs) -{ - memcpy(mData, rhs.mData, sizeof(Double) * N * M); - return *this; -} - - -/* - * charles::basics::Matrix<>::operator== -- - */ -template -bool -Matrix::operator==(const Matrix& rhs) - const -{ - for (UInt i = 0; i < N*M; i++) { - /* TODO: Use NearlyEqual. */ - if (mData[i] != rhs.mData[i]) { - return false; - } - } - return true; -} - - -/* - * charles::basics::Matrix<>::operator!= -- - */ -template -bool -Matrix::operator!=(const Matrix& rhs) - const -{ - return !(*this == rhs); -} - - -/* - * charles::basics::Matrix<>::operator() -- - */ -template -Double& -Matrix::operator()(UInt i, UInt j) -{ - assert(i < N && j < M); - return mData[i * N + j]; -} - - -/* - * charles::basics::Matrix<>::operator* -- - */ -template -Matrix -Matrix::operator*(const Double& rhs) - const -{ - return Matrix(*this) *= rhs; -} - - -template -Matrix& -Matrix::operator*=(const Double& rhs) -{ - for (size_t i = 0; i < N*M; i++) { - mData[i] *= rhs; - } - return *this; -} - - -template -Matrix -Matrix::operator/(const Double& rhs) - const -{ - return Matrix(*this) /= rhs; -} - - -template -Matrix& -Matrix::operator/=(const Double& rhs) -{ - return *this *= (1.0 / rhs); -} - - -/* - * charles::basics::Matrix<>::operator* -- - */ -template -template -Matrix -Matrix::operator*(Matrix rhs) - const -{ - Matrix result; - for (UInt i = 0; i < N; i++) { - for (UInt j = 0; j < P; j++) { - /* Each cell is Sigma(k=0, M)(lhs[ik] * rhs[kj]) */ - result(i, j) = 0.0; - for (UInt k = 0; k < M; k++) { - result(i, j) += mData[i*N + k] * rhs(k, j); - } - } - } - return result; -} - - -/* - * charles::basics::Matrix<>::CArray -- - */ -template -const Double* -Matrix::CArray() - const -{ - return mData; -} - - -/* - * charles::basics::operator* -- - */ -template -Matrix -operator*(const Double& lhs, - const Matrix& rhs) -{ - return rhs * lhs; -} +Matrix4 operator*(const Double &lhs, const Matrix4 &rhs); } /* namespace basics */ } /* namespace charles */ diff --git a/src/basics/vector.cc b/src/basics/vector.cc index 7d42a59..a3b6fac 100644 --- a/src/basics/vector.cc +++ b/src/basics/vector.cc @@ -4,6 +4,7 @@ */ #include +#include #include "basics/vector.hh" @@ -14,9 +15,18 @@ namespace basics { /* * charles::basics::Vector4::Vector4 -- */ -Vector4::Vector4(const Double& x, - const Double& y, - const Double& z) +Vector4::Vector4() +{ + bzero(mData, sizeof(Double) * 4); +} + + +/* + * charles::basics::Vector4::Vector4 -- + */ +Vector4::Vector4(Double x, + Double y, + Double z) { mData[0] = x; mData[1] = y; @@ -24,12 +34,7 @@ Vector4::Vector4(const Double& x, mData[3] = 1.0; } - -Vector4::Vector4(const Matrix<4,1>& rhs) -{ - memcpy(mData, rhs.CArray(), sizeof(Double) * 4); -} - +#pragma mark Component Access /* * charles::basics::Vector4::X -- @@ -40,7 +45,11 @@ Vector4::X() return mData[0]; } -const Double& + +/* + * charles::basics::Vector4::X -- + */ +Double Vector4::X() const { @@ -58,7 +67,10 @@ Vector4::Y() } -const Double& +/* + * charles::basics::Vector4::Y -- + */ +Double Vector4::Y() const { @@ -79,43 +91,87 @@ Vector4::Z() /* * charles::basics::Vector4::Z -- */ -const Double& +Double Vector4::Z() const { return mData[2]; } +#pragma mark Maths -#if 0 /* * charles::basics::Vector4::operator* -- */ Vector4 -Vector4::operator*(const Double& rhs) +Vector4::operator*(Double rhs) const { - return static_cast>(*this) * rhs; + return Vector4(*this) *= rhs; +} + + +/* + * charles::basics::Vector4::operator* -- + */ +Vector4 +Vector4::operator/(Double rhs) + const +{ + return Vector4(*this) /= rhs; +} + + +/* + * charles::basics::Vector4::operator*= -- + */ +Vector4& +Vector4::operator*=(Double rhs) +{ + for (int i = 0; i < 4; i++) { + mData[i] *= rhs; + } + return *this; +} + + +/* + * charles::basics::Vector4::operator/= -- + */ +Vector4& +Vector4::operator/=(Double rhs) +{ + return *this *= (1.0 / rhs); } -#endif /* * charles::basics::Vector4::operator+ -- */ Vector4 -Vector4::operator+(const Vector4& rhs) +Vector4::operator+(const Vector4 &rhs) const { return Vector4(*this) += rhs; } +/* + * charles::basics::Vector4::operator- -- + */ +Vector4 +Vector4::operator-(const Vector4 &rhs) + const +{ + return Vector4(*this) -= rhs; +} + + /* * charles::basics::Vector4::operator+= -- */ Vector4& -Vector4::operator+=(const Vector4& rhs) +Vector4::operator+=(const Vector4 &rhs) { mData[0] += rhs.mData[0]; mData[1] += rhs.mData[1]; @@ -124,22 +180,11 @@ Vector4::operator+=(const Vector4& rhs) } -/* - * charles::basics::Vector4::operator- -- - */ -Vector4 -Vector4::operator-(const Vector4& rhs) - const -{ - return Vector4(*this) -= rhs; -} - - /* * charles::basics::Vector4::operator-= -- */ Vector4& -Vector4::operator-=(const Vector4& rhs) +Vector4::operator-=(const Vector4 &rhs) { return *this += -rhs; } @@ -163,7 +208,7 @@ Double Vector4::Length2() const { - return mData[0] * mData[0] + mData[1] * mData[1] + mData[2] * mData[2]; + return X()*X() + Y()*Y() + Z()*Z(); } @@ -185,7 +230,7 @@ Double Vector4::Dot(const Vector4& rhs) const { - return mData[0] * rhs.mData[0] + mData[1] * rhs.mData[1] + mData[2] * rhs.mData[2]; + return X()*rhs.X() + Y()*rhs.Y() + Z()*rhs.Z(); } @@ -208,12 +253,7 @@ Vector4::Cross(const Vector4& rhs) Vector4& Vector4::Normalize() { - /* XXX: Is there some way to do this with the Matrix<>::operator/? */ - const Double len = Length(); - X() = X() / len; - Y() = Y() / len; - Z() = Z() / len; - return *this; + return *this /= Length(); } @@ -221,7 +261,7 @@ Vector4::Normalize() * charles::basics::operator* -- */ Vector4 -operator*(const Double& lhs, +operator*(Double lhs, const Vector4& rhs) { return rhs * lhs; @@ -232,9 +272,9 @@ operator*(const Double& lhs, * charles::basics::Normalized -- */ Vector4 -Normalized(const Vector4& v) +Normalized(Vector4 v) { - return Vector4(v).Normalize(); + return v.Normalize(); } diff --git a/src/basics/vector.hh b/src/basics/vector.hh index 787bb4f..a98a095 100644 --- a/src/basics/vector.hh +++ b/src/basics/vector.hh @@ -15,34 +15,50 @@ namespace charles { namespace basics { -template -struct Vector - : public Matrix -{ }; - - +/** A 4x1 matrix, used for specifying points and directions in 3D space. */ struct Vector4 - : public Vector<4> { - Vector4(const Double& x = 0.0, const Double& y = 0.0, const Double& z = 0.0); - Vector4(const Matrix<4,1>& m); + Vector4(); + Vector4(Double x, Double y, Double z); + Vector4 &operator=(const Vector4 &rhs); + + /** + * @defgroup Component access + * @{ + */ Double& X(); - const Double& X() const; + Double X() const; Double& Y(); - const Double& Y() const; + Double Y() const; Double& Z(); - const Double& Z() const; + Double Z() const; + /** @} */ -#if 0 - Vector4 operator*(const Double& rhs) const; -#endif + bool operator==(const Vector4 &rhs) const; + bool operator!=(const Vector4 &rhs) const; - Vector4 operator+(const Vector4& rhs) const; - Vector4& operator+=(const Vector4& rhs); - Vector4 operator-(const Vector4& rhs) const; - Vector4& operator-=(const Vector4& rhs); + /** + * @defgroup Scalar multiplication + * @{ + */ + Vector4 operator*(Double rhs) const; + Vector4 operator/(Double rhs) const; + Vector4 &operator*=(Double rhs); + Vector4 &operator/=(Double rhs); + /** @} */ + /** + * @defgroup Vector addition and subtraction + * @{ + */ + Vector4 operator+(const Vector4 &rhs) const; + Vector4 operator-(const Vector4 &rhs) const; + Vector4 &operator+=(const Vector4 &rhs); + Vector4 &operator-=(const Vector4 &rhs); + /** @} */ + + /** Negate this vector. */ Vector4 operator-() const; /** Get the length-squared of this vector. */ @@ -52,30 +68,33 @@ struct Vector4 Double Length() const; /** Get the dot product of `this` and `rhs`. */ - Double Dot(const Vector4& rhs) const; + Double Dot(const Vector4 &rhs) const; /** Get the cross product of `this` and `rhs`. */ Vector4 Cross(const Vector4& rhs) const; /** Normalize this vector. */ Vector4& Normalize(); + +private: + Double mData[4]; }; /** Scalar multiplication of vectors, with the scalar factor on the left. */ -Vector4 operator*(const Double& lhs, const Vector4& rhs); +Vector4 operator*(Double lhs, const Vector4 &rhs); -/** Normalize the given vector and return a copy of it. */ -Vector4 Normalized(const Vector4& v); +/** Normalize a copy of the given vector. */ +Vector4 Normalized(Vector4 v); -Vector4 LinearCombination(const Double k1, const Vector4& v1, - const Double k2, const Vector4& v2, - const Double k3, const Vector4& v3); +Vector4 LinearCombination(Double k1, const Vector4 &v1, + Double k2, const Vector4 &v2, + Double k3, const Vector4 &v3); -std::ostream& operator<<(std::ostream& ost, const Vector4& v); +std::ostream& operator<<(std::ostream &ost, const Vector4 &v); } /* namespace basics */ } /* namespace charles */ diff --git a/src/object.cc b/src/object.cc index c3f6bce..57db9c0 100644 --- a/src/object.cc +++ b/src/object.cc @@ -25,7 +25,7 @@ namespace charles { * charles::Object::Object -- */ Object::Object(const Vector4& origin) - : mTranslation(basics::TranslationMatrix(origin.X(), origin.Y(), origin.Z())), + : mTranslation(basics::Matrix4::Translation(origin.X(), origin.Y(), origin.Z())), mMaterial() { } From 620d5a5bc603aebbc9955663506076aae31297b7 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sun, 10 Aug 2014 11:38:55 -0700 Subject: [PATCH 72/92] Fill in missing Vector4 symbols Add assignment and call operators, bool operators, etc --- src/basics/vector.cc | 81 ++++++++++++++++++++++++++++++++++++++++++++ src/basics/vector.hh | 6 ++++ 2 files changed, 87 insertions(+) diff --git a/src/basics/vector.cc b/src/basics/vector.cc index a3b6fac..76e2b52 100644 --- a/src/basics/vector.cc +++ b/src/basics/vector.cc @@ -5,13 +5,19 @@ #include #include +#include +#include #include "basics/vector.hh" +#include "basics/util.hh" + namespace charles { namespace basics { +#pragma mark Constructors and Assignment + /* * charles::basics::Vector4::Vector4 -- */ @@ -34,6 +40,17 @@ Vector4::Vector4(Double x, mData[3] = 1.0; } + +/* + * charles::basics::Vector4::operator= -- + */ +Vector4& +Vector4::operator=(const Vector4 &rhs) +{ + memcpy(mData, rhs.mData, sizeof(Double) * 4); + return *this; +} + #pragma mark Component Access /* @@ -98,6 +115,70 @@ Vector4::Z() return mData[2]; } + +Double& +Vector4::operator()(UInt i) +{ + if (i >= 4) { + std::stringstream ss; + ss << "vector index out of bounds: i = " << i; + throw std::out_of_range(ss.str()); + } + return mData[i]; +} + + +Double +Vector4::operator()(UInt i) + const +{ + if (i >= 4) { + std::stringstream ss; + ss << "vector index out of bounds: i = " << i; + throw std::out_of_range(ss.str()); + } + return mData[i]; +} + + +/* + * charles::basics::Vector4::CArray -- + */ +const Double* +Vector4::CArray() + const +{ + return mData; +} + +#pragma mark Boolean Operators + +/* + * charles::basics::Vector4::operator== -- + */ +bool +Vector4::operator==(const Vector4 &rhs) + const +{ + for (UInt i = 0; i < 4; i++) { + if (!NearlyEqual(mData[i], rhs.mData[i])) { + return false; + } + } + return true; +} + + +/* + * charles::basics::Vector4::operator!= -- + */ +bool +Vector4::operator!=(const Vector4 &rhs) + const +{ + return !(*this == rhs); +} + #pragma mark Maths /* diff --git a/src/basics/vector.hh b/src/basics/vector.hh index a98a095..e8b99a2 100644 --- a/src/basics/vector.hh +++ b/src/basics/vector.hh @@ -33,6 +33,12 @@ struct Vector4 Double Y() const; Double& Z(); Double Z() const; + + Double &operator()(UInt i); + Double operator()(UInt i) const; + + /** Get the underlying C array. */ + const Double *CArray() const; /** @} */ bool operator==(const Vector4 &rhs) const; From 51fbba95e74402edf5fbb3f0dc978fdd584b6e0f Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sun, 10 Aug 2014 11:39:05 -0700 Subject: [PATCH 73/92] Rename some matrix tests --- test/test_basics.cc | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/test/test_basics.cc b/test/test_basics.cc index 98c7d71..dad6dae 100644 --- a/test/test_basics.cc +++ b/test/test_basics.cc @@ -248,7 +248,7 @@ TEST_F(Matrix4Test, ScalarMultiplication) } -TEST_F(Matrix4Test, SquareMatrixMultiplication) +TEST_F(Matrix4Test, MatrixMatrixMultiplication) { const Double p1Expect[] = {1045, 1690, 2735, 4425, 2137, 3454, 5591, 9045, @@ -267,20 +267,10 @@ TEST_F(Matrix4Test, SquareMatrixMultiplication) for (int i = 0; i < 16; i++) { EXPECT_EQ(p2.CArray()[i], p2Expect[i]); } - - /* Multiplication with the identity matrix produces the same matrix. */ - Matrix4 p3 = m1 * Matrix4::Identity(); - for (int i = 0; i < 16; i++) { - EXPECT_EQ(p3.CArray()[i], m1.CArray()[i]); - } - Matrix4 p4 = Matrix4::Identity() * m1; - for (int i = 0; i < 16; i++) { - EXPECT_EQ(p4.CArray()[i], m1.CArray()[i]); - } } -TEST_F(Matrix4Test, IdentityMultiplication) +TEST_F(Matrix4Test, MatrixIdentityMultiplication) { Matrix4 p1 = m1 * id; for (UInt i = 0; i < 16; i++) { @@ -294,7 +284,7 @@ TEST_F(Matrix4Test, IdentityMultiplication) } -TEST_F(Matrix4Test, VectorMultiplication) +TEST_F(Matrix4Test, IdentityVectorMultiplication) { Vector4 v1(1, 2, 3); From dd36ab6fe12f0b5973f679eb4393cdf9c43cc6bc Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sun, 10 Aug 2014 11:39:25 -0700 Subject: [PATCH 74/92] Fill in missing Matrix4 symbols --- src/basics/matrix.cc | 40 +++++++++++++++++++++++++++++++++------- src/basics/matrix.hh | 2 +- 2 files changed, 34 insertions(+), 8 deletions(-) diff --git a/src/basics/matrix.cc b/src/basics/matrix.cc index 5a3798b..6c24450 100644 --- a/src/basics/matrix.cc +++ b/src/basics/matrix.cc @@ -10,6 +10,7 @@ #include "basics/matrix.hh" #include "basics/util.hh" +#include "basics/vector.hh" namespace charles { @@ -47,9 +48,9 @@ Matrix4::Identity() * charles::basics::TranslationMatrix -- */ /* static */ Matrix4 -Translation(Double x, - Double y, - Double z) +Matrix4::Translation(Double x, + Double y, + Double z) { Matrix4 m = Matrix4::Identity(); m(0,3) = x; @@ -129,14 +130,15 @@ Matrix4::operator!=(const Matrix4 &rhs) * charles::basics::Matrix4::operator() -- */ Double& -Matrix4::operator()(UInt i, UInt j) +Matrix4::operator()(UInt i, + UInt j) { if (i >= 4 || j >= 4) { std::stringstream ss; ss << "matrix index out of bounds: i = " << i << ", j = " << j; throw std::out_of_range(ss.str()); } - return mData[i * 4 + j]; + return mData[i*4 + j]; } @@ -144,10 +146,16 @@ Matrix4::operator()(UInt i, UInt j) * charles::basics::Matrix4::operator() -- */ Double -Matrix4::operator()(UInt i, UInt j) +Matrix4::operator()(UInt i, + UInt j) const { - return operator()(i, j); + if (i >= 4 || j >= 4) { + std::stringstream ss; + ss << "matrix index out of bounds: i = " << i << ", j = " << j; + throw std::out_of_range(ss.str()); + } + return mData[i*4 + j]; } @@ -229,6 +237,24 @@ Matrix4::operator*(const Matrix4& rhs) } +/* + * charles::basics::Matrix4::operator* -- + */ +Vector4 +Matrix4::operator*(const Vector4 &rhs) + const +{ + Vector4 result; + for (UInt i = 0; i < 4; i++) { + result(i) = 0.0; + for (UInt k = 0; k < 4; k++) { + result(i) += mData[i*4 + k] * rhs(k); + } + } + return result; +} + + /* * charles::basics::operator* -- */ diff --git a/src/basics/matrix.hh b/src/basics/matrix.hh index c7224a9..2128e45 100644 --- a/src/basics/matrix.hh +++ b/src/basics/matrix.hh @@ -80,7 +80,7 @@ protected: /** Scalar multiplication, scalar factor on the left. */ -Matrix4 operator*(const Double &lhs, const Matrix4 &rhs); +Matrix4 operator*(Double lhs, const Matrix4 &rhs); } /* namespace basics */ } /* namespace charles */ From 4d4dc91ff46e57c72b89a30b9ba5d86a26efee21 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sun, 10 Aug 2014 16:57:34 -0700 Subject: [PATCH 75/92] Add Matrix4 Inverse and Transpose Transpose is easy, with a bool flag to determine whether to access elements in row-major or column-major format. Inverse is more difficult, so this change only does translation inverses. --- src/basics/matrix.cc | 69 +++++++++++++++++++++++++++++++++++++++++--- src/basics/matrix.hh | 16 ++++++++++ test/test_basics.cc | 18 ++++++++++++ 3 files changed, 99 insertions(+), 4 deletions(-) diff --git a/src/basics/matrix.cc b/src/basics/matrix.cc index 6c24450..5779794 100644 --- a/src/basics/matrix.cc +++ b/src/basics/matrix.cc @@ -65,7 +65,8 @@ Matrix4::Translation(Double x, * charles::basics::Matrix4::Matrix4 -- */ Matrix4::Matrix4() - : mData() + : mData(), + mTransposed(false) { } @@ -73,6 +74,7 @@ Matrix4::Matrix4() * charles::basics::Matrix4::Matrix4 -- */ Matrix4::Matrix4(const Double data[16]) + : mTransposed(false) { memcpy(mData, data, sizeof(Double) * 16); } @@ -83,7 +85,13 @@ Matrix4::Matrix4(const Double data[16]) */ Matrix4::Matrix4(const Matrix4 &rhs) : Matrix4(rhs.mData) -{ } +{ + /* + * Needs to be in the body instead of the initializer list because + * (apparently) delegating constructors must be the only thing in the list. + */ + mTransposed = rhs.mTransposed; +} /* @@ -93,6 +101,7 @@ Matrix4& Matrix4::operator=(const Matrix4 &rhs) { memcpy(mData, rhs.mData, sizeof(Double) * 16); + mTransposed = rhs.mTransposed; return *this; } @@ -138,7 +147,12 @@ Matrix4::operator()(UInt i, ss << "matrix index out of bounds: i = " << i << ", j = " << j; throw std::out_of_range(ss.str()); } - return mData[i*4 + j]; + + if (!mTransposed) { + return mData[i*4 + j]; + } else { + return mData[i + j*4]; + } } @@ -155,7 +169,11 @@ Matrix4::operator()(UInt i, ss << "matrix index out of bounds: i = " << i << ", j = " << j; throw std::out_of_range(ss.str()); } - return mData[i*4 + j]; + if (!mTransposed) { + return mData[i*4 + j]; + } else { + return mData[i + j*4]; + } } @@ -255,6 +273,28 @@ Matrix4::operator*(const Vector4 &rhs) } +/* + * charles::basics::Matrix4::Transpose -- + */ +Matrix4& +Matrix4::Transpose() +{ + mTransposed = !mTransposed; + return *this; +} + + +Matrix4& +Matrix4::Inverse() +{ + /* XXX: Only translation matrices are supported right now. */ + operator()(0,3) = -operator()(0,3); + operator()(1,3) = -operator()(1,3); + operator()(2,3) = -operator()(2,3); + return *this; +} + + /* * charles::basics::operator* -- */ @@ -266,6 +306,27 @@ operator*(Double lhs, return rhs * lhs; } + +/* + * charles::basics::Transposed -- + */ +Matrix4 +Transposed(Matrix4 m) +{ + return m.Transpose(); +} + + +/* + * charles::basics::Inverse -- + */ +Matrix4 +Inverse(Matrix4 m) +{ + return m.Inverse(); +} + + } /* namespace mespace */ } /* namespace charles */ diff --git a/src/basics/matrix.hh b/src/basics/matrix.hh index 2128e45..ba8309c 100644 --- a/src/basics/matrix.hh +++ b/src/basics/matrix.hh @@ -73,15 +73,31 @@ struct Matrix4 Vector4 operator*(const Vector4 &rhs) const; /** @} */ + Matrix4& Transpose(); + Matrix4& Inverse(); + protected: /** The matrix data */ Double mData[16]; + + /** + * `true` if the matrix has been transposed (i.e. should be indexed in + * column-major format). + */ + bool mTransposed; }; /** Scalar multiplication, scalar factor on the left. */ Matrix4 operator*(Double lhs, const Matrix4 &rhs); + +/** Transpose the given matrix. */ +Matrix4 Transposed(Matrix4 rhs); + +/** Invert the given matrix. */ +Matrix4 Inverse(Matrix4 rhs); + } /* namespace basics */ } /* namespace charles */ diff --git a/test/test_basics.cc b/test/test_basics.cc index dad6dae..a5b99bb 100644 --- a/test/test_basics.cc +++ b/test/test_basics.cc @@ -293,3 +293,21 @@ TEST_F(Matrix4Test, IdentityVectorMultiplication) EXPECT_EQ(p1.Y(), v1.Y()); EXPECT_EQ(p1.Z(), v1.Z()); } + + +TEST_F(Matrix4Test, Transpose) +{ + Matrix4 t1 = Transposed(m1); + for (UInt i = 0; i < 4; i++) { + for (UInt j = 0; j < 4; j++) { + EXPECT_EQ(m1(i,j), t1(j,i)); + } + } + + t1.Transpose(); + for (UInt i = 0; i < 4; i++) { + for (UInt j = 0; j < 4; j++) { + EXPECT_EQ(m1(i,j), t1(i,j)); + } + } +} From 56fff1178e4509a80925d9fe266341f79034f47a Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sun, 10 Aug 2014 16:58:05 -0700 Subject: [PATCH 76/92] ToObjectSpace copies the Ray anyway, so pass by value --- src/object.cc | 9 ++++----- src/object.hh | 2 +- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/object.cc b/src/object.cc index 57db9c0..3b0bdf6 100644 --- a/src/object.cc +++ b/src/object.cc @@ -85,13 +85,12 @@ Object::Normal(const Vector4& p) * charles::Object::ToObjectSpace -- */ Ray -Object::ToObjectSpace(const Ray& ray) +Object::ToObjectSpace(Ray ray) const { - Ray objRay(ray); - objRay.origin = mTranslation * objRay.origin; - objRay.direction = mTranslation * objRay.direction; - return objRay; + ray.origin = mTranslation * ray.origin; + ray.direction = mTranslation * ray.direction; + return ray; } diff --git a/src/object.hh b/src/object.hh index 6696d72..9bb47a7 100644 --- a/src/object.hh +++ b/src/object.hh @@ -59,7 +59,7 @@ protected: private: /** Convert `ray` to object space from global space. */ - basics::Ray ToObjectSpace(const basics::Ray& ray) const; + basics::Ray ToObjectSpace(basics::Ray ray) const; /** Convert `v` to object space from global space. */ basics::Vector4 ToObjectSpace(const basics::Vector4& v) const; From 97b37d3c535e57696a280db225f4b40b889acb6f Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Mon, 11 Aug 2014 07:58:47 -0700 Subject: [PATCH 77/92] Just little tweaks Mostly style, also the name of the Transposed() function -> Transpose(). --- src/basics/matrix.cc | 2 +- src/basics/matrix.hh | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/basics/matrix.cc b/src/basics/matrix.cc index 5779794..92fa60a 100644 --- a/src/basics/matrix.cc +++ b/src/basics/matrix.cc @@ -311,7 +311,7 @@ operator*(Double lhs, * charles::basics::Transposed -- */ Matrix4 -Transposed(Matrix4 m) +Transpose(Matrix4 m) { return m.Transpose(); } diff --git a/src/basics/matrix.hh b/src/basics/matrix.hh index ba8309c..b6bae04 100644 --- a/src/basics/matrix.hh +++ b/src/basics/matrix.hh @@ -73,8 +73,8 @@ struct Matrix4 Vector4 operator*(const Vector4 &rhs) const; /** @} */ - Matrix4& Transpose(); - Matrix4& Inverse(); + Matrix4 &Transpose(); + Matrix4 &Inverse(); protected: /** The matrix data */ @@ -93,10 +93,10 @@ Matrix4 operator*(Double lhs, const Matrix4 &rhs); /** Transpose the given matrix. */ -Matrix4 Transposed(Matrix4 rhs); +Matrix4 Transpose(Matrix4 m); /** Invert the given matrix. */ -Matrix4 Inverse(Matrix4 rhs); +Matrix4 Inverse(Matrix4 m); } /* namespace basics */ } /* namespace charles */ From 8af03c3f3d7ce9fe2d5bf243f53065e9c2ccb7b0 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Fri, 15 Aug 2014 22:32:44 -0700 Subject: [PATCH 78/92] Implement Object::Place Places the object by manipulating its translation matrix. --- src/basics/matrix.cc | 10 ++++++++++ src/basics/matrix.hh | 1 + src/object.cc | 10 ++++++++++ src/object.hh | 3 +++ 4 files changed, 24 insertions(+) diff --git a/src/basics/matrix.cc b/src/basics/matrix.cc index 92fa60a..1a89f7f 100644 --- a/src/basics/matrix.cc +++ b/src/basics/matrix.cc @@ -44,6 +44,16 @@ Matrix4::Identity() } +/* + * charles::basics::Translation -- + */ +/* static */ Matrix4 +Matrix4::Translation(const Vector4& p) +{ + return Translation(p.X(), p.Y(), p.Z()); +} + + /* * charles::basics::TranslationMatrix -- */ diff --git a/src/basics/matrix.hh b/src/basics/matrix.hh index b6bae04..4e6ebdf 100644 --- a/src/basics/matrix.hh +++ b/src/basics/matrix.hh @@ -30,6 +30,7 @@ struct Matrix4 /** Create a 4x4 translation matrix. */ static Matrix4 Translation(Double x, Double y, Double z); + static Matrix4 Translation(const Vector4 &p); Matrix4(); Matrix4(const Double *data); diff --git a/src/object.cc b/src/object.cc index 3b0bdf6..e9afe35 100644 --- a/src/object.cc +++ b/src/object.cc @@ -47,6 +47,16 @@ Object::GetMaterial() } +/* + * charles::Object::Place -- + */ +void +Object::Place(const Vector4 &p) +{ + mTranslation = Matrix4::Translation(p); +} + + /* * charles::Object::SetMaterial -- */ diff --git a/src/object.hh b/src/object.hh index 9bb47a7..6b9a58b 100644 --- a/src/object.hh +++ b/src/object.hh @@ -27,6 +27,8 @@ struct Object Material& GetMaterial(); void SetMaterial(const Material& material); + void Place(const basics::Vector4 &p); + /** * Determine if the given ray intersects with this object. Converts the * ray's origin and direction to object space before calling the protected @@ -67,6 +69,7 @@ private: /** Convert `v` to global space from object space. */ basics::Vector4 FromObjectSpace(const basics::Vector4& v) const; + /** A translation matrix from global coordinates to this object's space. */ basics::Matrix4 mTranslation; From bbbac6ff926bca61f6b1591fcfbaffcbb88d5b6f Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Fri, 15 Aug 2014 22:33:22 -0700 Subject: [PATCH 79/92] Fix up Object object space conversions - Ray directions shouldn't be translated - Implement vector translation to global space --- src/object.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/object.cc b/src/object.cc index e9afe35..80b2151 100644 --- a/src/object.cc +++ b/src/object.cc @@ -16,6 +16,7 @@ using charles::basics::Ray; +using charles::basics::Matrix4; using charles::basics::Vector4; @@ -25,7 +26,7 @@ namespace charles { * charles::Object::Object -- */ Object::Object(const Vector4& origin) - : mTranslation(basics::Matrix4::Translation(origin.X(), origin.Y(), origin.Z())), + : mTranslation(Matrix4::Translation(origin.X(), origin.Y(), origin.Z())), mMaterial() { } @@ -99,7 +100,6 @@ Object::ToObjectSpace(Ray ray) const { ray.origin = mTranslation * ray.origin; - ray.direction = mTranslation * ray.direction; return ray; } @@ -122,7 +122,7 @@ Vector4 Object::FromObjectSpace(const Vector4& v) const { - return v; + return Inverse(mTranslation) * v; } From 050d87bd6fc9e6b3339e994ef1b58ae806d1c80c Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Fri, 15 Aug 2014 22:33:34 -0700 Subject: [PATCH 80/92] Place an object by its origin (only applies to spheres) --- src/yaml/objectParser.cc | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/yaml/objectParser.cc b/src/yaml/objectParser.cc index 614a9d5..330b001 100644 --- a/src/yaml/objectParser.cc +++ b/src/yaml/objectParser.cc @@ -174,12 +174,9 @@ ObjectParser::HandleOriginEvent(yaml_event_t& event) } auto onDone = [this](Vector4 origin) { - /* TODO: Once Place() and Move() are implemented on Object, use that. */ -#if 0 - mObject->SetOrigin(origin); + mObject->Place(origin); mSection = NoSection; SetShouldExpectKey(true); -#endif }; GetParsers().push(new Vector4Parser(GetScene(), GetParsers(), onDone)); From 1daf1619efcaaef50bcba5104167050ba6a49b32 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Wed, 6 Aug 2014 20:46:35 -0700 Subject: [PATCH 81/92] A few more objects for the oneBox scene -- it's not really one box anymore --- scenes/oneBox.yml | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/scenes/oneBox.yml b/scenes/oneBox.yml index 987c2ae..e998d3c 100644 --- a/scenes/oneBox.yml +++ b/scenes/oneBox.yml @@ -1,10 +1,18 @@ --- !Scene dimensions: [800, 600] camera: !Camera.Perspective - origin: [3, 2, -3] - direction: [-0.6396, -0.4264, 0.6396] + origin: [7.48, 6.5, 5.34] + lookAt: [0, 0, 0] objects: - !Object.Box - near: [-0.5, -0.5, -0.5] - far: [0.5, 0.5, 0.5] - color: [0.2, 0.328, 1.0] + near: [-1, -1, -1] + far: [1, 1, 1] + color: [1, 0, 0] + - !Object.Sphere + origin: [1.5, 0, 0] + radius: 0.25 + color: [0, 1, 0] + - !Object.Plane + normal: [0, 1, 0] + distance: 1 + color: [0, 0, 1] From c45d698424a9b88ea1f3e351045cc56afbcf4bb3 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 16 Aug 2014 00:43:43 -0700 Subject: [PATCH 82/92] Get a column vector of a matrix --- src/basics/matrix.cc | 9 +++++++++ src/basics/matrix.hh | 1 + src/basics/vector.cc | 13 ++++++++++++- src/basics/vector.hh | 1 + src/object.cc | 2 ++ src/object.hh | 3 +++ 6 files changed, 28 insertions(+), 1 deletion(-) diff --git a/src/basics/matrix.cc b/src/basics/matrix.cc index 1a89f7f..bd95a71 100644 --- a/src/basics/matrix.cc +++ b/src/basics/matrix.cc @@ -6,6 +6,7 @@ #include #include #include +#include #include "basics/matrix.hh" @@ -187,6 +188,14 @@ Matrix4::operator()(UInt i, } +Vector4 +Matrix4::Column(const UInt i) + const noexcept +{ + return Vector4(operator()(i,0), operator()(i,1), operator()(i,2), operator()(i,3)); +} + + /* * charles::basics::Matrix4::CArray -- */ diff --git a/src/basics/matrix.hh b/src/basics/matrix.hh index 4e6ebdf..9a93164 100644 --- a/src/basics/matrix.hh +++ b/src/basics/matrix.hh @@ -47,6 +47,7 @@ struct Matrix4 */ Double& operator()(UInt i, UInt j); Double operator()(UInt i, UInt j) const; + Vector4 Column(const UInt i) const noexcept; /** Get the underlying C array */ const Double *CArray() const; diff --git a/src/basics/vector.cc b/src/basics/vector.cc index 76e2b52..02a07ff 100644 --- a/src/basics/vector.cc +++ b/src/basics/vector.cc @@ -33,11 +33,22 @@ Vector4::Vector4() Vector4::Vector4(Double x, Double y, Double z) + : Vector4(x, y, z, 1.0) +{ } + + +/* + * charles::basics::Vector4::Vector4 -- + */ +Vector4::Vector4(Double x, + Double y, + Double z, + Double w) { mData[0] = x; mData[1] = y; mData[2] = z; - mData[3] = 1.0; + mData[3] = w; } diff --git a/src/basics/vector.hh b/src/basics/vector.hh index e8b99a2..b83a5c2 100644 --- a/src/basics/vector.hh +++ b/src/basics/vector.hh @@ -20,6 +20,7 @@ struct Vector4 { Vector4(); Vector4(Double x, Double y, Double z); + Vector4(Double x, Double y, Double z, Double w); Vector4 &operator=(const Vector4 &rhs); diff --git a/src/object.cc b/src/object.cc index 80b2151..419e507 100644 --- a/src/object.cc +++ b/src/object.cc @@ -144,7 +144,9 @@ std::ostream& operator<<(std::ostream& ost, const Object& object) { + ost << "["; object.Write(ost); + ost << " translate=" << object.mTranslation.Column(3) << "]"; return ost; } diff --git a/src/object.hh b/src/object.hh index 6b9a58b..ee2fca2 100644 --- a/src/object.hh +++ b/src/object.hh @@ -60,6 +60,9 @@ protected: virtual basics::Vector4 DoNormal(const basics::Vector4& p) const = 0; private: + friend std::ostream& operator<<(std::ostream& ost, const Object& object); + + /** Convert `ray` to object space from global space. */ basics::Ray ToObjectSpace(basics::Ray ray) const; From dc6efc5e65bb3cd52527a90500174b0a85a7b4d1 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 16 Aug 2014 00:44:07 -0700 Subject: [PATCH 83/92] Fix up Transposed -> Tranpose in unit tests --- test/test_basics.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/test_basics.cc b/test/test_basics.cc index a5b99bb..d539efe 100644 --- a/test/test_basics.cc +++ b/test/test_basics.cc @@ -297,7 +297,7 @@ TEST_F(Matrix4Test, IdentityVectorMultiplication) TEST_F(Matrix4Test, Transpose) { - Matrix4 t1 = Transposed(m1); + Matrix4 t1 = Transpose(m1); for (UInt i = 0; i < 4; i++) { for (UInt j = 0; j < 4; j++) { EXPECT_EQ(m1(i,j), t1(j,i)); From 7e3cc3c3ed81a14576c3db9eb2109f8ec04d698f Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 16 Aug 2014 08:33:12 -0700 Subject: [PATCH 84/92] Copy properties of log tracer The log tracer needs to copy its parameters, otherwise weird things happen. --- src/log.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/log.hh b/src/log.hh index 24727ef..31e3a23 100644 --- a/src/log.hh +++ b/src/log.hh @@ -69,8 +69,8 @@ struct Tracer ~Tracer(); private: - const std::string& mName; - const std::string& mFunction; + const std::string mName; + const std::string mFunction; }; From 3a846ec2825a85d5052db6673d1f730193099ecd Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 16 Aug 2014 08:52:40 -0700 Subject: [PATCH 85/92] Add -n option for "should render" --- src/charles.cc | 19 +++++++++++++------ 1 file changed, 13 insertions(+), 6 deletions(-) diff --git a/src/charles.cc b/src/charles.cc index d684b86..e27947a 100644 --- a/src/charles.cc +++ b/src/charles.cc @@ -42,13 +42,15 @@ main(int argc, PointLight *l1 = new PointLight(Vector4(4.0, 6.0, 1.0), Color::White, 0.8); scene.AddLight(l1); + bool shouldRender = true; + std::string logFilename; unsigned int logLevel = 0; std::string outfile, infile; int opt; - while ((opt = getopt(argc, (char *const *)argv, "hl:L:o:v:")) != -1) { + while ((opt = getopt(argc, (char *const *)argv, "hl:L:no:v:")) != -1) { switch (opt) { case 'h': usage(argv[0]); @@ -60,6 +62,9 @@ main(int argc, case 'L': logLevel = std::stoul(optarg); break; + case 'n': + shouldRender = false; + break; case 'o': outfile = optarg; break; @@ -96,12 +101,14 @@ main(int argc, } /* Call tracer. */ - LOG_INFO << "Beginning render"; - scene.Render(); + if (shouldRender) { + LOG_INFO << "Beginning render"; + scene.Render(); - /* Write rendered scene to PNG file. */ - PNGWriter writer; - scene.Write(writer, outfile); + /* Write rendered scene to PNG file. */ + PNGWriter writer; + scene.Write(writer, outfile); + } if (logLevel > 0) { Log::Close(); From 8460f2205e9cd574c665fec545303a3ffc002b38 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 16 Aug 2014 08:54:33 -0700 Subject: [PATCH 86/92] Remake test_object -> testObject.cc This was a *really* old class... --- test/testObject.cc | 6 +++ test/test_object.c | 94 ---------------------------------------------- 2 files changed, 6 insertions(+), 94 deletions(-) create mode 100644 test/testObject.cc delete mode 100644 test/test_object.c diff --git a/test/testObject.cc b/test/testObject.cc new file mode 100644 index 0000000..87d7da8 --- /dev/null +++ b/test/testObject.cc @@ -0,0 +1,6 @@ +/* test_object.cc + * vim: set tw=80: + * Eryn Wells + */ + + diff --git a/test/test_object.c b/test/test_object.c deleted file mode 100644 index 7aa655a..0000000 --- a/test/test_object.c +++ /dev/null @@ -1,94 +0,0 @@ -/* test_object.c - * - * Unit tests for the object module. - * - * Eryn Wells - */ - -#include - -#include - -#include "object.h" -#include "test_asserts.h" -#include "test_suites.h" - - -void check_sphere_intersection(Object *sphere, Ray ray, Vector3 *tvectors, int ntvectors); - - -START_TEST(test_sphere_does_intersect) -{ - // Create a sphere at the origin of radius 1. - Object *sphere = object_init(ObjectTypeSphere); - object_sphere_set_radius(sphere, 1.0); - - Vector3 loc, dir; - Vector3 tvectors[2]; - Ray ray; - - loc = vector_init(0, 0, -5); - dir = vector_init(0, 0, 1); - ray = ray_init(loc, dir); - tvectors[0] = vector_init(0, 0, -1); - tvectors[1] = vector_init(0, 0, 1); - check_sphere_intersection(sphere, ray, tvectors, 2); - - loc = vector_init(0, -5, 0); - dir = vector_init(0, 1, 0); - ray = ray_init(loc, dir); - tvectors[0] = vector_init(0, -1, 0); - tvectors[1] = vector_init(0, 1, 0); - check_sphere_intersection(sphere, ray, tvectors, 2); -} -END_TEST - - -void -check_sphere_intersection(Object *sphere, Ray ray, Vector3 *tvectors, int ntvectors) -{ - float *t; - int nints = object_does_intersect(sphere, ray, &t); - ck_assert(nints == ntvectors); - - Vector3 rp; - for (int i = 0; i < nints; i++) { - rp = ray_parameterize(ray, t[i]); - test_assert_within_epsilon(rp.x, tvectors[i].x, 1e-4); - test_assert_within_epsilon(rp.y, tvectors[i].y, 1e-4); - test_assert_within_epsilon(rp.z, tvectors[i].z, 1e-4); - } - - if (nints > 0) { - free(t); - } -} - - -START_TEST(test_sphere_point_lies_on_surface) -{ - ck_assert(0); -} -END_TEST - - -START_TEST(test_sphere_compute_normal) -{ - ck_assert(0); -} -END_TEST - - -Suite * -test_object_create_suite() -{ - Suite *s = suite_create("object"); - - TCase *tc_sphere = tcase_create("sphere"); - tcase_add_test(tc_sphere, test_sphere_does_intersect); - tcase_add_test(tc_sphere, test_sphere_point_lies_on_surface); - tcase_add_test(tc_sphere, test_sphere_compute_normal); - suite_add_tcase(s, tc_sphere); - - return s; -} From 22297da809b8bbe5f916853b7a0e744c976c21ae Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 16 Aug 2014 16:56:53 -0700 Subject: [PATCH 87/92] Add includes to testObject.cc No unit tests for objects yet... --- test/testObject.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/testObject.cc b/test/testObject.cc index 87d7da8..f855cbe 100644 --- a/test/testObject.cc +++ b/test/testObject.cc @@ -3,4 +3,6 @@ * Eryn Wells */ +#include "gtest/gtest.h" +#include "object.hh" From 09c5e29f6364433a4bbd5c20222d1be93bbb1c5f Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 16 Aug 2014 16:57:08 -0700 Subject: [PATCH 88/92] Add a vector translation multiplication test --- test/test_basics.cc | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/test/test_basics.cc b/test/test_basics.cc index d539efe..b07ec78 100644 --- a/test/test_basics.cc +++ b/test/test_basics.cc @@ -295,6 +295,18 @@ TEST_F(Matrix4Test, IdentityVectorMultiplication) } +TEST_F(Matrix4Test, TranslationVectorMultiplication) +{ + Matrix4 tr = Matrix4::Translation(1, 2, 3); + Vector4 v1(3, 7, 9); + + Vector4 p1 = tr * v1; + EXPECT_EQ(p1.X(), 4.0); + EXPECT_EQ(p1.Y(), 9.0); + EXPECT_EQ(p1.Z(), 12.0); +} + + TEST_F(Matrix4Test, Transpose) { Matrix4 t1 = Transpose(m1); From 10195c607cfb1a3110419e8f390c4a331de426ad Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 16 Aug 2014 16:57:58 -0700 Subject: [PATCH 89/92] operator<< for pretty-printing an entire Matrix4 --- src/basics/matrix.cc | 29 +++++++++++++++++++++++++++++ src/basics/matrix.hh | 4 +++- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/src/basics/matrix.cc b/src/basics/matrix.cc index bd95a71..598ff73 100644 --- a/src/basics/matrix.cc +++ b/src/basics/matrix.cc @@ -346,6 +346,35 @@ Inverse(Matrix4 m) } +/* + * charles::basics::operator<< -- + */ +std::ostream& +operator<<(std::ostream &ost, + const Matrix4 &m) +{ + ost << "["; + for (UInt i = 0; i < 4; i++) { + if (i != 0) { + ost << " "; + } + ost << "["; + for (UInt j = 0; j < 4; j++) { + ost << m(i,j); + if (j < 3) { + ost << " "; + } + } + ost << "]"; + if (i < 3) { + ost << "\n"; + } + } + ost << "]"; + return ost; +} + + } /* namespace mespace */ } /* namespace charles */ diff --git a/src/basics/matrix.hh b/src/basics/matrix.hh index 9a93164..bd434fa 100644 --- a/src/basics/matrix.hh +++ b/src/basics/matrix.hh @@ -93,13 +93,15 @@ protected: /** Scalar multiplication, scalar factor on the left. */ Matrix4 operator*(Double lhs, const Matrix4 &rhs); - /** Transpose the given matrix. */ Matrix4 Transpose(Matrix4 m); /** Invert the given matrix. */ Matrix4 Inverse(Matrix4 m); + +std::ostream& operator<<(std::ostream &ost, const Matrix4 &m); + } /* namespace basics */ } /* namespace charles */ From d518d282d424a86eca1060ce646661b3eeb94e19 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 16 Aug 2014 20:35:01 -0700 Subject: [PATCH 90/92] Notes in Matrix4 about using std::copy MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Not entirely sure what it does, but it's standard C++… :shrugs: --- src/basics/matrix.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/basics/matrix.cc b/src/basics/matrix.cc index 598ff73..b8f6ba6 100644 --- a/src/basics/matrix.cc +++ b/src/basics/matrix.cc @@ -87,6 +87,7 @@ Matrix4::Matrix4() Matrix4::Matrix4(const Double data[16]) : mTransposed(false) { + /* TODO: Replace with std::copy */ memcpy(mData, data, sizeof(Double) * 16); } @@ -111,6 +112,7 @@ Matrix4::Matrix4(const Matrix4 &rhs) Matrix4& Matrix4::operator=(const Matrix4 &rhs) { + /* TODO: Replace with std::copy */ memcpy(mData, rhs.mData, sizeof(Double) * 16); mTransposed = rhs.mTransposed; return *this; From 791fdaa14a77ea92d669b5f8e2b920a809473fa0 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 16 Aug 2014 20:35:49 -0700 Subject: [PATCH 91/92] Use the Vector4 version of Matrix4::Translation for object origins --- src/object.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/object.cc b/src/object.cc index 419e507..e268033 100644 --- a/src/object.cc +++ b/src/object.cc @@ -26,7 +26,7 @@ namespace charles { * charles::Object::Object -- */ Object::Object(const Vector4& origin) - : mTranslation(Matrix4::Translation(origin.X(), origin.Y(), origin.Z())), + : mTranslation(Matrix4::Translation(origin)), mMaterial() { } From 0a43eb81aaf84def98cd6e878403ce70887b06f1 Mon Sep 17 00:00:00 2001 From: Eryn Wells Date: Sat, 16 Aug 2014 20:36:02 -0700 Subject: [PATCH 92/92] Explicitly declare overrides in Sphere --- src/objectSphere.hh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/objectSphere.hh b/src/objectSphere.hh index 7ad62d1..e5e9499 100644 --- a/src/objectSphere.hh +++ b/src/objectSphere.hh @@ -27,8 +27,8 @@ public: void Write(std::ostream& ost) const; protected: - bool DoIntersect(const basics::Ray& ray, TVector& t, Stats& stats) const; - basics::Vector4 DoNormal(const basics::Vector4& p) const; + bool DoIntersect(const basics::Ray& ray, TVector& t, Stats& stats) const override; + basics::Vector4 DoNormal(const basics::Vector4& p) const override; private: Double mRadius;