mirror of
https://git.mirrors.martin98.com/https://github.com/syoyo/tinygltf.git
synced 2025-08-10 05:49:00 +08:00
Remove old nanort/nanosg code. Keep the gltf-loader class on hand
Signed-off by: Arthur Brainville (Ybalrid) <ybalrid@ybalrid.info>
This commit is contained in:
parent
c7ae1a3e76
commit
fb7ebb955e
@ -1,33 +0,0 @@
|
||||
# Raytrace example
|
||||
|
||||
Simple raytracing example with OpenGL preview
|
||||
|
||||
## Status
|
||||
|
||||
Not working yet. Still in work in progress.
|
||||
|
||||
## Build
|
||||
|
||||
### Linux or macOS
|
||||
|
||||
```
|
||||
$ premake5 gmake
|
||||
$ make
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
||||
```
|
||||
$ premake5 vs2015
|
||||
```
|
||||
|
||||
|
||||
## Third party libraries and its icenses.
|
||||
|
||||
* picojson : BSD license.
|
||||
* bt3gui : zlib license.
|
||||
* glew : BSD/MIT license.
|
||||
* tinyobjloader : MIT license.
|
||||
* glm : The Happy Bunny License (Modified MIT License). Copyright (c) 2005 - 2017 G-Truc Creation
|
||||
* ImGui : The MIT License (MIT). Copyright (c) 2014-2015 Omar Cornut and ImGui contributors
|
||||
* ImGuizmo : The MIT License (MIT). Copyright (c) 2016 Cedric Guillemet
|
@ -1,9 +0,0 @@
|
||||
{ "gltf_filename" : "../../models/Cube/Cube.gltf",
|
||||
"scene_scale" : 1.0,
|
||||
"width" : 512,
|
||||
"height" : 512,
|
||||
"eye" : [0, 2.5, 15],
|
||||
"up" : [0, 1, 0],
|
||||
"look_at" : [0, 0, 0],
|
||||
"dummy" : 0
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@ -1,69 +0,0 @@
|
||||
#ifndef EXAMPLE_MATERIAL_H_
|
||||
#define EXAMPLE_MATERIAL_H_
|
||||
|
||||
#include <cstdlib>
|
||||
|
||||
namespace example {
|
||||
|
||||
// TODO(syoyo): Support PBR material.
|
||||
|
||||
struct Material {
|
||||
// float ambient[3];
|
||||
float diffuse[3];
|
||||
float specular[3];
|
||||
// float reflection[3];
|
||||
// float refraction[3];
|
||||
int id;
|
||||
int diffuse_texid;
|
||||
int specular_texid;
|
||||
// int reflection_texid;
|
||||
// int transparency_texid;
|
||||
// int bump_texid;
|
||||
// int normal_texid; // normal map
|
||||
// int alpha_texid; // alpha map
|
||||
|
||||
Material() {
|
||||
// ambient[0] = 0.0;
|
||||
// ambient[1] = 0.0;
|
||||
// ambient[2] = 0.0;
|
||||
diffuse[0] = 0.5;
|
||||
diffuse[1] = 0.5;
|
||||
diffuse[2] = 0.5;
|
||||
specular[0] = 0.5;
|
||||
specular[1] = 0.5;
|
||||
specular[2] = 0.5;
|
||||
// reflection[0] = 0.0;
|
||||
// reflection[1] = 0.0;
|
||||
// reflection[2] = 0.0;
|
||||
// refraction[0] = 0.0;
|
||||
// refraction[1] = 0.0;
|
||||
// refraction[2] = 0.0;
|
||||
id = -1;
|
||||
diffuse_texid = -1;
|
||||
specular_texid = -1;
|
||||
// reflection_texid = -1;
|
||||
// transparency_texid = -1;
|
||||
// bump_texid = -1;
|
||||
// normal_texid = -1;
|
||||
// alpha_texid = -1;
|
||||
}
|
||||
};
|
||||
|
||||
struct Texture {
|
||||
int width;
|
||||
int height;
|
||||
int components;
|
||||
unsigned char* image;
|
||||
|
||||
Texture() {
|
||||
width = -1;
|
||||
height = -1;
|
||||
components = -1;
|
||||
image = NULL;
|
||||
}
|
||||
};
|
||||
|
||||
} // namespace example
|
||||
|
||||
|
||||
#endif // EXAMPLE_MATERIAL_H_
|
@ -1,216 +0,0 @@
|
||||
#include <cstdio>
|
||||
#include <cmath>
|
||||
|
||||
#include "matrix.h"
|
||||
|
||||
//using namespace mallie;
|
||||
|
||||
static inline float vdot(float a[3], float b[3]) {
|
||||
return a[0] * b[0] + a[1] * b[1] + a[2] * b[2];
|
||||
}
|
||||
|
||||
static inline void vcross(float c[3], float a[3], float b[3]) {
|
||||
c[0] = a[1] * b[2] - a[2] * b[1];
|
||||
c[1] = a[2] * b[0] - a[0] * b[2];
|
||||
c[2] = a[0] * b[1] - a[1] * b[0];
|
||||
}
|
||||
|
||||
static inline float vlength(float v[3]) {
|
||||
float len2 = vdot(v, v);
|
||||
if (std::abs(len2) > 1.0e-30) {
|
||||
return sqrt(len2);
|
||||
}
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
static void vnormalize(float v[3]) {
|
||||
float len = vlength(v);
|
||||
if (std::abs(len) > 1.0e-30) {
|
||||
float inv_len = 1.0f / len;
|
||||
v[0] *= inv_len;
|
||||
v[1] *= inv_len;
|
||||
v[2] *= inv_len;
|
||||
}
|
||||
}
|
||||
|
||||
void Matrix::Print(float m[4][4]) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
printf("m[%d] = %f, %f, %f, %f\n", i, m[i][0], m[i][1], m[i][2], m[i][3]);
|
||||
}
|
||||
}
|
||||
|
||||
void Matrix::LookAt(float m[4][4], float eye[3], float lookat[3],
|
||||
float up[3]) {
|
||||
|
||||
float u[3], v[3];
|
||||
float look[3];
|
||||
look[0] = lookat[0] - eye[0];
|
||||
look[1] = lookat[1] - eye[1];
|
||||
look[2] = lookat[2] - eye[2];
|
||||
vnormalize(look);
|
||||
|
||||
vcross(u, look, up);
|
||||
vnormalize(u);
|
||||
|
||||
vcross(v, u, look);
|
||||
vnormalize(v);
|
||||
|
||||
#if 0
|
||||
m[0][0] = u[0];
|
||||
m[0][1] = v[0];
|
||||
m[0][2] = -look[0];
|
||||
m[0][3] = 0.0;
|
||||
|
||||
m[1][0] = u[1];
|
||||
m[1][1] = v[1];
|
||||
m[1][2] = -look[1];
|
||||
m[1][3] = 0.0;
|
||||
|
||||
m[2][0] = u[2];
|
||||
m[2][1] = v[2];
|
||||
m[2][2] = -look[2];
|
||||
m[2][3] = 0.0;
|
||||
|
||||
m[3][0] = eye[0];
|
||||
m[3][1] = eye[1];
|
||||
m[3][2] = eye[2];
|
||||
m[3][3] = 1.0;
|
||||
#else
|
||||
m[0][0] = u[0];
|
||||
m[1][0] = v[0];
|
||||
m[2][0] = -look[0];
|
||||
m[3][0] = eye[0];
|
||||
|
||||
m[0][1] = u[1];
|
||||
m[1][1] = v[1];
|
||||
m[2][1] = -look[1];
|
||||
m[3][1] = eye[1];
|
||||
|
||||
m[0][2] = u[2];
|
||||
m[1][2] = v[2];
|
||||
m[2][2] = -look[2];
|
||||
m[3][2] = eye[2];
|
||||
|
||||
m[0][3] = 0.0;
|
||||
m[1][3] = 0.0;
|
||||
m[2][3] = 0.0;
|
||||
m[3][3] = 1.0;
|
||||
|
||||
#endif
|
||||
}
|
||||
|
||||
void Matrix::Inverse(float m[4][4]) {
|
||||
/*
|
||||
* codes from intel web
|
||||
* cramer's rule version
|
||||
*/
|
||||
int i, j;
|
||||
float tmp[12]; /* tmp array for pairs */
|
||||
float tsrc[16]; /* array of transpose source matrix */
|
||||
float det; /* determinant */
|
||||
|
||||
/* transpose matrix */
|
||||
for (i = 0; i < 4; i++) {
|
||||
tsrc[i] = m[i][0];
|
||||
tsrc[i + 4] = m[i][1];
|
||||
tsrc[i + 8] = m[i][2];
|
||||
tsrc[i + 12] = m[i][3];
|
||||
}
|
||||
|
||||
/* calculate pair for first 8 elements(cofactors) */
|
||||
tmp[0] = tsrc[10] * tsrc[15];
|
||||
tmp[1] = tsrc[11] * tsrc[14];
|
||||
tmp[2] = tsrc[9] * tsrc[15];
|
||||
tmp[3] = tsrc[11] * tsrc[13];
|
||||
tmp[4] = tsrc[9] * tsrc[14];
|
||||
tmp[5] = tsrc[10] * tsrc[13];
|
||||
tmp[6] = tsrc[8] * tsrc[15];
|
||||
tmp[7] = tsrc[11] * tsrc[12];
|
||||
tmp[8] = tsrc[8] * tsrc[14];
|
||||
tmp[9] = tsrc[10] * tsrc[12];
|
||||
tmp[10] = tsrc[8] * tsrc[13];
|
||||
tmp[11] = tsrc[9] * tsrc[12];
|
||||
|
||||
/* calculate first 8 elements(cofactors) */
|
||||
m[0][0] = tmp[0] * tsrc[5] + tmp[3] * tsrc[6] + tmp[4] * tsrc[7];
|
||||
m[0][0] -= tmp[1] * tsrc[5] + tmp[2] * tsrc[6] + tmp[5] * tsrc[7];
|
||||
m[0][1] = tmp[1] * tsrc[4] + tmp[6] * tsrc[6] + tmp[9] * tsrc[7];
|
||||
m[0][1] -= tmp[0] * tsrc[4] + tmp[7] * tsrc[6] + tmp[8] * tsrc[7];
|
||||
m[0][2] = tmp[2] * tsrc[4] + tmp[7] * tsrc[5] + tmp[10] * tsrc[7];
|
||||
m[0][2] -= tmp[3] * tsrc[4] + tmp[6] * tsrc[5] + tmp[11] * tsrc[7];
|
||||
m[0][3] = tmp[5] * tsrc[4] + tmp[8] * tsrc[5] + tmp[11] * tsrc[6];
|
||||
m[0][3] -= tmp[4] * tsrc[4] + tmp[9] * tsrc[5] + tmp[10] * tsrc[6];
|
||||
m[1][0] = tmp[1] * tsrc[1] + tmp[2] * tsrc[2] + tmp[5] * tsrc[3];
|
||||
m[1][0] -= tmp[0] * tsrc[1] + tmp[3] * tsrc[2] + tmp[4] * tsrc[3];
|
||||
m[1][1] = tmp[0] * tsrc[0] + tmp[7] * tsrc[2] + tmp[8] * tsrc[3];
|
||||
m[1][1] -= tmp[1] * tsrc[0] + tmp[6] * tsrc[2] + tmp[9] * tsrc[3];
|
||||
m[1][2] = tmp[3] * tsrc[0] + tmp[6] * tsrc[1] + tmp[11] * tsrc[3];
|
||||
m[1][2] -= tmp[2] * tsrc[0] + tmp[7] * tsrc[1] + tmp[10] * tsrc[3];
|
||||
m[1][3] = tmp[4] * tsrc[0] + tmp[9] * tsrc[1] + tmp[10] * tsrc[2];
|
||||
m[1][3] -= tmp[5] * tsrc[0] + tmp[8] * tsrc[1] + tmp[11] * tsrc[2];
|
||||
|
||||
/* calculate pairs for second 8 elements(cofactors) */
|
||||
tmp[0] = tsrc[2] * tsrc[7];
|
||||
tmp[1] = tsrc[3] * tsrc[6];
|
||||
tmp[2] = tsrc[1] * tsrc[7];
|
||||
tmp[3] = tsrc[3] * tsrc[5];
|
||||
tmp[4] = tsrc[1] * tsrc[6];
|
||||
tmp[5] = tsrc[2] * tsrc[5];
|
||||
tmp[6] = tsrc[0] * tsrc[7];
|
||||
tmp[7] = tsrc[3] * tsrc[4];
|
||||
tmp[8] = tsrc[0] * tsrc[6];
|
||||
tmp[9] = tsrc[2] * tsrc[4];
|
||||
tmp[10] = tsrc[0] * tsrc[5];
|
||||
tmp[11] = tsrc[1] * tsrc[4];
|
||||
|
||||
/* calculate second 8 elements(cofactors) */
|
||||
m[2][0] = tmp[0] * tsrc[13] + tmp[3] * tsrc[14] + tmp[4] * tsrc[15];
|
||||
m[2][0] -= tmp[1] * tsrc[13] + tmp[2] * tsrc[14] + tmp[5] * tsrc[15];
|
||||
m[2][1] = tmp[1] * tsrc[12] + tmp[6] * tsrc[14] + tmp[9] * tsrc[15];
|
||||
m[2][1] -= tmp[0] * tsrc[12] + tmp[7] * tsrc[14] + tmp[8] * tsrc[15];
|
||||
m[2][2] = tmp[2] * tsrc[12] + tmp[7] * tsrc[13] + tmp[10] * tsrc[15];
|
||||
m[2][2] -= tmp[3] * tsrc[12] + tmp[6] * tsrc[13] + tmp[11] * tsrc[15];
|
||||
m[2][3] = tmp[5] * tsrc[12] + tmp[8] * tsrc[13] + tmp[11] * tsrc[14];
|
||||
m[2][3] -= tmp[4] * tsrc[12] + tmp[9] * tsrc[13] + tmp[10] * tsrc[14];
|
||||
m[3][0] = tmp[2] * tsrc[10] + tmp[5] * tsrc[11] + tmp[1] * tsrc[9];
|
||||
m[3][0] -= tmp[4] * tsrc[11] + tmp[0] * tsrc[9] + tmp[3] * tsrc[10];
|
||||
m[3][1] = tmp[8] * tsrc[11] + tmp[0] * tsrc[8] + tmp[7] * tsrc[10];
|
||||
m[3][1] -= tmp[6] * tsrc[10] + tmp[9] * tsrc[11] + tmp[1] * tsrc[8];
|
||||
m[3][2] = tmp[6] * tsrc[9] + tmp[11] * tsrc[11] + tmp[3] * tsrc[8];
|
||||
m[3][2] -= tmp[10] * tsrc[11] + tmp[2] * tsrc[8] + tmp[7] * tsrc[9];
|
||||
m[3][3] = tmp[10] * tsrc[10] + tmp[4] * tsrc[8] + tmp[9] * tsrc[9];
|
||||
m[3][3] -= tmp[8] * tsrc[9] + tmp[11] * tsrc[0] + tmp[5] * tsrc[8];
|
||||
|
||||
/* calculate determinant */
|
||||
det = tsrc[0] * m[0][0] + tsrc[1] * m[0][1] + tsrc[2] * m[0][2] +
|
||||
tsrc[3] * m[0][3];
|
||||
|
||||
/* calculate matrix inverse */
|
||||
det = 1.0f / det;
|
||||
|
||||
for (j = 0; j < 4; j++) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
m[j][i] *= det;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Matrix::Mult(float dst[4][4], float m0[4][4], float m1[4][4]) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
dst[i][j] = 0;
|
||||
for (int k = 0; k < 4; ++k) {
|
||||
dst[i][j] += m0[k][j] * m1[i][k];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Matrix::MultV(float dst[3], float m[4][4], float v[3]) {
|
||||
// printf("v = %f, %f, %f\n", v[0], v[1], v[2]);
|
||||
dst[0] = m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2] + m[3][0];
|
||||
dst[1] = m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2] + m[3][1];
|
||||
dst[2] = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2];
|
||||
// printf("m = %f, %f, %f\n", m[3][0], m[3][1], m[3][2]);
|
||||
// printf("dst = %f, %f, %f\n", dst[0], dst[1], dst[2]);
|
||||
}
|
@ -1,182 +0,0 @@
|
||||
#ifndef EXAMPLE_MESH_H_
|
||||
#define EXAMPLE_MESH_H_
|
||||
|
||||
#include <vector>
|
||||
#include <algorithm>
|
||||
#include <cmath>
|
||||
|
||||
namespace example {
|
||||
|
||||
|
||||
template<typename T>
|
||||
inline void lerp(T dst[3], const T v0[3], const T v1[3], const T v2[3], float u, float v) {
|
||||
dst[0] = (static_cast<T>(1.0) - u - v) * v0[0] + u * v1[0] + v * v2[0];
|
||||
dst[1] = (static_cast<T>(1.0) - u - v) * v0[1] + u * v1[1] + v * v2[1];
|
||||
dst[2] = (static_cast<T>(1.0) - u - v) * v0[2] + u * v1[2] + v * v2[2];
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline T vlength(const T v[3]) {
|
||||
const T d = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
|
||||
if (std::fabs(d) > std::numeric_limits<T>::epsilon()) {
|
||||
return std::sqrt(d);
|
||||
} else {
|
||||
return static_cast<T>(0.0);
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void vnormalize(T dst[3], const T v[3]) {
|
||||
dst[0] = v[0];
|
||||
dst[1] = v[1];
|
||||
dst[2] = v[2];
|
||||
const T len = vlength(v);
|
||||
if (std::fabs(len) > std::numeric_limits<T>::epsilon()) {
|
||||
const T inv_len = static_cast<T>(1.0) / len;
|
||||
dst[0] *= inv_len;
|
||||
dst[1] *= inv_len;
|
||||
dst[2] *= inv_len;
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void vcross(T dst[3], const T a[3], const T b[3]) {
|
||||
dst[0] = a[1] * b[2] - a[2] * b[1];
|
||||
dst[1] = a[2] * b[0] - a[0] * b[2];
|
||||
dst[2] = a[0] * b[1] - a[1] * b[0];
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
inline void vsub(T dst[3], const T a[3], const T b[3]) {
|
||||
dst[0] = a[0] - b[0];
|
||||
dst[1] = a[1] - b[1];
|
||||
dst[2] = a[2] - b[2];
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
inline void calculate_normal(T Nn[3], const T v0[3], const T v1[3], const T v2[3]) {
|
||||
T v10[3];
|
||||
T v20[3];
|
||||
|
||||
vsub(v10, v1, v0);
|
||||
vsub(v20, v2, v0);
|
||||
|
||||
T N[3];
|
||||
vcross(N, v20, v10);
|
||||
vnormalize(Nn, N);
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
class Mesh {
|
||||
public:
|
||||
std::string name;
|
||||
|
||||
std::vector<T> vertices; /// [xyz] * num_vertices
|
||||
std::vector<T> facevarying_normals; /// [xyz] * 3(triangle) * num_faces
|
||||
std::vector<T> facevarying_tangents; /// [xyz] * 3(triangle) * num_faces
|
||||
std::vector<T> facevarying_binormals; /// [xyz] * 3(triangle) * num_faces
|
||||
std::vector<T> facevarying_uvs; /// [xy] * 3(triangle) * num_faces
|
||||
std::vector<T>
|
||||
facevarying_vertex_colors; /// [xyz] * 3(triangle) * num_faces
|
||||
std::vector<unsigned int> faces; /// triangle x num_faces
|
||||
std::vector<unsigned int> material_ids; /// index x num_faces
|
||||
|
||||
T pivot_xform[4][4];
|
||||
|
||||
// --- Required methods in Scene::Traversal. ---
|
||||
|
||||
///
|
||||
/// Get the geometric normal and the shading normal at `face_idx' th face.
|
||||
///
|
||||
void GetNormal(T Ng[3], T Ns[3], const unsigned int face_idx, const T u, const T v) const {
|
||||
// Compute geometric normal.
|
||||
unsigned int f0, f1, f2;
|
||||
T v0[3], v1[3], v2[3];
|
||||
|
||||
f0 = faces[3 * face_idx + 0];
|
||||
f1 = faces[3 * face_idx + 1];
|
||||
f2 = faces[3 * face_idx + 2];
|
||||
|
||||
v0[0] = vertices[3 * f0 + 0];
|
||||
v0[1] = vertices[3 * f0 + 1];
|
||||
v0[2] = vertices[3 * f0 + 2];
|
||||
|
||||
v1[0] = vertices[3 * f1 + 0];
|
||||
v1[1] = vertices[3 * f1 + 1];
|
||||
v1[2] = vertices[3 * f1 + 2];
|
||||
|
||||
v2[0] = vertices[3 * f2 + 0];
|
||||
v2[1] = vertices[3 * f2 + 1];
|
||||
v2[2] = vertices[3 * f2 + 2];
|
||||
|
||||
calculate_normal(Ng, v0, v1, v2);
|
||||
|
||||
if (facevarying_normals.size() > 0) {
|
||||
|
||||
T n0[3], n1[3], n2[3];
|
||||
|
||||
n0[0] = facevarying_normals[9 * face_idx + 0];
|
||||
n0[1] = facevarying_normals[9 * face_idx + 1];
|
||||
n0[2] = facevarying_normals[9 * face_idx + 2];
|
||||
|
||||
n1[0] = facevarying_normals[9 * face_idx + 3];
|
||||
n1[1] = facevarying_normals[9 * face_idx + 4];
|
||||
n1[2] = facevarying_normals[9 * face_idx + 5];
|
||||
|
||||
n2[0] = facevarying_normals[9 * face_idx + 6];
|
||||
n2[1] = facevarying_normals[9 * face_idx + 7];
|
||||
n2[2] = facevarying_normals[9 * face_idx + 8];
|
||||
|
||||
lerp(Ns, n0, n1, n2, u, v);
|
||||
|
||||
} else {
|
||||
|
||||
// Use geometric normal.
|
||||
Ns[0] = Ng[0];
|
||||
Ns[1] = Ng[1];
|
||||
Ns[2] = Ng[2];
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// --- end of required methods in Scene::Traversal. ---
|
||||
|
||||
///
|
||||
/// Get texture coordinate at `face_idx' th face.
|
||||
///
|
||||
void GetTexCoord(T tcoord[3], const unsigned int face_idx, const T u, const T v) {
|
||||
|
||||
if (facevarying_uvs.size() > 0) {
|
||||
|
||||
T t0[3], t1[3], t2[3];
|
||||
|
||||
t0[0] = facevarying_uvs[6 * face_idx + 0];
|
||||
t0[1] = facevarying_uvs[6 * face_idx + 1];
|
||||
t0[2] = static_cast<T>(0.0);
|
||||
|
||||
t1[0] = facevarying_uvs[6 * face_idx + 2];
|
||||
t1[1] = facevarying_uvs[6 * face_idx + 3];
|
||||
t1[2] = static_cast<T>(0.0);
|
||||
|
||||
t2[0] = facevarying_uvs[6 * face_idx + 4];
|
||||
t2[1] = facevarying_uvs[6 * face_idx + 5];
|
||||
t2[2] = static_cast<T>(0.0);
|
||||
|
||||
lerp(tcoord, t0, t1, t2, u, v);
|
||||
|
||||
} else {
|
||||
|
||||
tcoord[0] = static_cast<T>(0.0);
|
||||
tcoord[1] = static_cast<T>(0.0);
|
||||
tcoord[2] = static_cast<T>(0.0);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
} // namespace example
|
||||
|
||||
#endif // EXAMPLE_MESH_H_
|
File diff suppressed because it is too large
Load Diff
@ -1,900 +0,0 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2017 Light Transport Entertainment, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef NANOSG_H_
|
||||
#define NANOSG_H_
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifndef NOMINMAX
|
||||
#define NOMINMAX
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include <limits>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
|
||||
#include "nanort.h"
|
||||
|
||||
namespace nanosg {
|
||||
|
||||
template<class T>
|
||||
class PrimitiveInterface;
|
||||
|
||||
template<class T>
|
||||
class PrimitiveInterface{
|
||||
public:
|
||||
void print(){ static_cast<T &>(this)->print(); }
|
||||
};
|
||||
|
||||
class SpherePrimitive : PrimitiveInterface<SpherePrimitive> {
|
||||
public:
|
||||
void print(){ std::cout << "Sphere" << std::endl; }
|
||||
};
|
||||
|
||||
// 4x4 matrix
|
||||
template <typename T> class Matrix {
|
||||
public:
|
||||
Matrix();
|
||||
~Matrix();
|
||||
|
||||
static void Print(T m[4][4]) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
printf("m[%d] = %f, %f, %f, %f\n", i, m[i][0], m[i][1], m[i][2], m[i][3]);
|
||||
}
|
||||
}
|
||||
|
||||
static void Identity(T m[4][4]) {
|
||||
m[0][0] = static_cast<T>(1);
|
||||
m[0][1] = static_cast<T>(0);
|
||||
m[0][2] = static_cast<T>(0);
|
||||
m[0][3] = static_cast<T>(0);
|
||||
m[1][0] = static_cast<T>(0);
|
||||
m[1][1] = static_cast<T>(1);
|
||||
m[1][2] = static_cast<T>(0);
|
||||
m[1][3] = static_cast<T>(0);
|
||||
m[2][0] = static_cast<T>(0);
|
||||
m[2][1] = static_cast<T>(0);
|
||||
m[2][2] = static_cast<T>(1);
|
||||
m[2][3] = static_cast<T>(0);
|
||||
m[3][0] = static_cast<T>(0);
|
||||
m[3][1] = static_cast<T>(0);
|
||||
m[3][2] = static_cast<T>(0);
|
||||
m[3][3] = static_cast<T>(1);
|
||||
}
|
||||
|
||||
static void Copy(T dst[4][4], const T src[4][4]) {
|
||||
memcpy(dst, src, sizeof(T) * 16);
|
||||
}
|
||||
|
||||
static void Inverse(T m[4][4]) {
|
||||
/*
|
||||
* codes from intel web
|
||||
* cramer's rule version
|
||||
*/
|
||||
int i, j;
|
||||
T tmp[12]; /* tmp array for pairs */
|
||||
T tsrc[16]; /* array of transpose source matrix */
|
||||
T det; /* determinant */
|
||||
|
||||
/* transpose matrix */
|
||||
for (i = 0; i < 4; i++) {
|
||||
tsrc[i] = m[i][0];
|
||||
tsrc[i + 4] = m[i][1];
|
||||
tsrc[i + 8] = m[i][2];
|
||||
tsrc[i + 12] = m[i][3];
|
||||
}
|
||||
|
||||
/* calculate pair for first 8 elements(cofactors) */
|
||||
tmp[0] = tsrc[10] * tsrc[15];
|
||||
tmp[1] = tsrc[11] * tsrc[14];
|
||||
tmp[2] = tsrc[9] * tsrc[15];
|
||||
tmp[3] = tsrc[11] * tsrc[13];
|
||||
tmp[4] = tsrc[9] * tsrc[14];
|
||||
tmp[5] = tsrc[10] * tsrc[13];
|
||||
tmp[6] = tsrc[8] * tsrc[15];
|
||||
tmp[7] = tsrc[11] * tsrc[12];
|
||||
tmp[8] = tsrc[8] * tsrc[14];
|
||||
tmp[9] = tsrc[10] * tsrc[12];
|
||||
tmp[10] = tsrc[8] * tsrc[13];
|
||||
tmp[11] = tsrc[9] * tsrc[12];
|
||||
|
||||
/* calculate first 8 elements(cofactors) */
|
||||
m[0][0] = tmp[0] * tsrc[5] + tmp[3] * tsrc[6] + tmp[4] * tsrc[7];
|
||||
m[0][0] -= tmp[1] * tsrc[5] + tmp[2] * tsrc[6] + tmp[5] * tsrc[7];
|
||||
m[0][1] = tmp[1] * tsrc[4] + tmp[6] * tsrc[6] + tmp[9] * tsrc[7];
|
||||
m[0][1] -= tmp[0] * tsrc[4] + tmp[7] * tsrc[6] + tmp[8] * tsrc[7];
|
||||
m[0][2] = tmp[2] * tsrc[4] + tmp[7] * tsrc[5] + tmp[10] * tsrc[7];
|
||||
m[0][2] -= tmp[3] * tsrc[4] + tmp[6] * tsrc[5] + tmp[11] * tsrc[7];
|
||||
m[0][3] = tmp[5] * tsrc[4] + tmp[8] * tsrc[5] + tmp[11] * tsrc[6];
|
||||
m[0][3] -= tmp[4] * tsrc[4] + tmp[9] * tsrc[5] + tmp[10] * tsrc[6];
|
||||
m[1][0] = tmp[1] * tsrc[1] + tmp[2] * tsrc[2] + tmp[5] * tsrc[3];
|
||||
m[1][0] -= tmp[0] * tsrc[1] + tmp[3] * tsrc[2] + tmp[4] * tsrc[3];
|
||||
m[1][1] = tmp[0] * tsrc[0] + tmp[7] * tsrc[2] + tmp[8] * tsrc[3];
|
||||
m[1][1] -= tmp[1] * tsrc[0] + tmp[6] * tsrc[2] + tmp[9] * tsrc[3];
|
||||
m[1][2] = tmp[3] * tsrc[0] + tmp[6] * tsrc[1] + tmp[11] * tsrc[3];
|
||||
m[1][2] -= tmp[2] * tsrc[0] + tmp[7] * tsrc[1] + tmp[10] * tsrc[3];
|
||||
m[1][3] = tmp[4] * tsrc[0] + tmp[9] * tsrc[1] + tmp[10] * tsrc[2];
|
||||
m[1][3] -= tmp[5] * tsrc[0] + tmp[8] * tsrc[1] + tmp[11] * tsrc[2];
|
||||
|
||||
/* calculate pairs for second 8 elements(cofactors) */
|
||||
tmp[0] = tsrc[2] * tsrc[7];
|
||||
tmp[1] = tsrc[3] * tsrc[6];
|
||||
tmp[2] = tsrc[1] * tsrc[7];
|
||||
tmp[3] = tsrc[3] * tsrc[5];
|
||||
tmp[4] = tsrc[1] * tsrc[6];
|
||||
tmp[5] = tsrc[2] * tsrc[5];
|
||||
tmp[6] = tsrc[0] * tsrc[7];
|
||||
tmp[7] = tsrc[3] * tsrc[4];
|
||||
tmp[8] = tsrc[0] * tsrc[6];
|
||||
tmp[9] = tsrc[2] * tsrc[4];
|
||||
tmp[10] = tsrc[0] * tsrc[5];
|
||||
tmp[11] = tsrc[1] * tsrc[4];
|
||||
|
||||
/* calculate second 8 elements(cofactors) */
|
||||
m[2][0] = tmp[0] * tsrc[13] + tmp[3] * tsrc[14] + tmp[4] * tsrc[15];
|
||||
m[2][0] -= tmp[1] * tsrc[13] + tmp[2] * tsrc[14] + tmp[5] * tsrc[15];
|
||||
m[2][1] = tmp[1] * tsrc[12] + tmp[6] * tsrc[14] + tmp[9] * tsrc[15];
|
||||
m[2][1] -= tmp[0] * tsrc[12] + tmp[7] * tsrc[14] + tmp[8] * tsrc[15];
|
||||
m[2][2] = tmp[2] * tsrc[12] + tmp[7] * tsrc[13] + tmp[10] * tsrc[15];
|
||||
m[2][2] -= tmp[3] * tsrc[12] + tmp[6] * tsrc[13] + tmp[11] * tsrc[15];
|
||||
m[2][3] = tmp[5] * tsrc[12] + tmp[8] * tsrc[13] + tmp[11] * tsrc[14];
|
||||
m[2][3] -= tmp[4] * tsrc[12] + tmp[9] * tsrc[13] + tmp[10] * tsrc[14];
|
||||
m[3][0] = tmp[2] * tsrc[10] + tmp[5] * tsrc[11] + tmp[1] * tsrc[9];
|
||||
m[3][0] -= tmp[4] * tsrc[11] + tmp[0] * tsrc[9] + tmp[3] * tsrc[10];
|
||||
m[3][1] = tmp[8] * tsrc[11] + tmp[0] * tsrc[8] + tmp[7] * tsrc[10];
|
||||
m[3][1] -= tmp[6] * tsrc[10] + tmp[9] * tsrc[11] + tmp[1] * tsrc[8];
|
||||
m[3][2] = tmp[6] * tsrc[9] + tmp[11] * tsrc[11] + tmp[3] * tsrc[8];
|
||||
m[3][2] -= tmp[10] * tsrc[11] + tmp[2] * tsrc[8] + tmp[7] * tsrc[9];
|
||||
m[3][3] = tmp[10] * tsrc[10] + tmp[4] * tsrc[8] + tmp[9] * tsrc[9];
|
||||
m[3][3] -= tmp[8] * tsrc[9] + tmp[11] * tsrc[0] + tmp[5] * tsrc[8];
|
||||
|
||||
/* calculate determinant */
|
||||
det = tsrc[0] * m[0][0] + tsrc[1] * m[0][1] + tsrc[2] * m[0][2] +
|
||||
tsrc[3] * m[0][3];
|
||||
|
||||
/* calculate matrix inverse */
|
||||
det = static_cast<T>(1.0) / det;
|
||||
|
||||
for (j = 0; j < 4; j++) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
m[j][i] *= det;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Transpose(T m[4][4]) {
|
||||
T t[4][4];
|
||||
|
||||
// Transpose
|
||||
for (int j = 0; j < 4; j++) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
t[j][i] = m[i][j];
|
||||
}
|
||||
}
|
||||
|
||||
// Copy
|
||||
for (int j = 0; j < 4; j++) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
m[j][i] = t[j][i];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void Mult(T dst[4][4], const T m0[4][4], const T m1[4][4]) {
|
||||
for (int i = 0; i < 4; ++i) {
|
||||
for (int j = 0; j < 4; ++j) {
|
||||
dst[i][j] = 0;
|
||||
for (int k = 0; k < 4; ++k) {
|
||||
dst[i][j] += m0[k][j] * m1[i][k];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void MultV(T dst[3], const T m[4][4], const T v[3]) {
|
||||
T tmp[3];
|
||||
tmp[0] = m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2] + m[3][0];
|
||||
tmp[1] = m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2] + m[3][1];
|
||||
tmp[2] = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2];
|
||||
dst[0] = tmp[0];
|
||||
dst[1] = tmp[1];
|
||||
dst[2] = tmp[2];
|
||||
}
|
||||
|
||||
static void MultV(nanort::real3<T> &dst, const T m[4][4], const T v[3]) {
|
||||
T tmp[3];
|
||||
tmp[0] = m[0][0] * v[0] + m[1][0] * v[1] + m[2][0] * v[2] + m[3][0];
|
||||
tmp[1] = m[0][1] * v[0] + m[1][1] * v[1] + m[2][1] * v[2] + m[3][1];
|
||||
tmp[2] = m[0][2] * v[0] + m[1][2] * v[1] + m[2][2] * v[2] + m[3][2];
|
||||
dst[0] = tmp[0];
|
||||
dst[1] = tmp[1];
|
||||
dst[2] = tmp[2];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
//typedef Matrix<float> Matrixf;
|
||||
//typedef Matrix<double> Matrixd;
|
||||
|
||||
template<typename T>
|
||||
static void XformBoundingBox(T xbmin[3], // out
|
||||
T xbmax[3], // out
|
||||
T bmin[3], T bmax[3],
|
||||
T m[4][4]) {
|
||||
|
||||
// create bounding vertex from (bmin, bmax)
|
||||
T b[8][3];
|
||||
|
||||
b[0][0] = bmin[0];
|
||||
b[0][1] = bmin[1];
|
||||
b[0][2] = bmin[2];
|
||||
b[1][0] = bmax[0];
|
||||
b[1][1] = bmin[1];
|
||||
b[1][2] = bmin[2];
|
||||
b[2][0] = bmin[0];
|
||||
b[2][1] = bmax[1];
|
||||
b[2][2] = bmin[2];
|
||||
b[3][0] = bmax[0];
|
||||
b[3][1] = bmax[1];
|
||||
b[3][2] = bmin[2];
|
||||
|
||||
b[4][0] = bmin[0];
|
||||
b[4][1] = bmin[1];
|
||||
b[4][2] = bmax[2];
|
||||
b[5][0] = bmax[0];
|
||||
b[5][1] = bmin[1];
|
||||
b[5][2] = bmax[2];
|
||||
b[6][0] = bmin[0];
|
||||
b[6][1] = bmax[1];
|
||||
b[6][2] = bmax[2];
|
||||
b[7][0] = bmax[0];
|
||||
b[7][1] = bmax[1];
|
||||
b[7][2] = bmax[2];
|
||||
|
||||
T xb[8][3];
|
||||
for (int i = 0; i < 8; i++) {
|
||||
Matrix<T>::MultV(xb[i], m, b[i]);
|
||||
}
|
||||
|
||||
xbmin[0] = xb[0][0];
|
||||
xbmin[1] = xb[0][1];
|
||||
xbmin[2] = xb[0][2];
|
||||
xbmax[0] = xb[0][0];
|
||||
xbmax[1] = xb[0][1];
|
||||
xbmax[2] = xb[0][2];
|
||||
|
||||
for (int i = 1; i < 8; i++) {
|
||||
|
||||
xbmin[0] = std::min(xb[i][0], xbmin[0]);
|
||||
xbmin[1] = std::min(xb[i][1], xbmin[1]);
|
||||
xbmin[2] = std::min(xb[i][2], xbmin[2]);
|
||||
|
||||
xbmax[0] = std::max(xb[i][0], xbmax[0]);
|
||||
xbmax[1] = std::max(xb[i][1], xbmax[1]);
|
||||
xbmax[2] = std::max(xb[i][2], xbmax[2]);
|
||||
}
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
struct Intersection
|
||||
{
|
||||
// required fields.
|
||||
T t; // hit distance
|
||||
unsigned int prim_id; // primitive ID of the hit
|
||||
float u;
|
||||
float v;
|
||||
|
||||
unsigned int node_id; // node ID of the hit.
|
||||
nanort::real3<T> P; // intersection point
|
||||
nanort::real3<T> Ns; // shading normal
|
||||
nanort::real3<T> Ng; // geometric normal
|
||||
};
|
||||
|
||||
///
|
||||
/// Renderable node
|
||||
///
|
||||
template<typename T, class M>
|
||||
class Node
|
||||
{
|
||||
public:
|
||||
typedef Node<T, M> type;
|
||||
|
||||
explicit Node(const M *mesh)
|
||||
: mesh_(mesh)
|
||||
{
|
||||
xbmin_[0] = xbmin_[1] = xbmin_[2] = std::numeric_limits<T>::max();
|
||||
xbmax_[0] = xbmax_[1] = xbmax_[2] = -std::numeric_limits<T>::max();
|
||||
|
||||
lbmin_[0] = lbmin_[1] = lbmin_[2] = std::numeric_limits<T>::max();
|
||||
lbmax_[0] = lbmax_[1] = lbmax_[2] = -std::numeric_limits<T>::max();
|
||||
|
||||
Matrix<T>::Identity(local_xform_);
|
||||
Matrix<T>::Identity(xform_);
|
||||
Matrix<T>::Identity(inv_xform_);
|
||||
Matrix<T>::Identity(inv_xform33_); inv_xform33_[3][3] = static_cast<T>(0.0);
|
||||
Matrix<T>::Identity(inv_transpose_xform33_); inv_transpose_xform33_[3][3] = static_cast<T>(0.0);
|
||||
|
||||
}
|
||||
|
||||
~Node() {}
|
||||
|
||||
void Copy(const type &rhs) {
|
||||
Matrix<T>::Copy(local_xform_, rhs.local_xform_);
|
||||
Matrix<T>::Copy(xform_, rhs.xform_);
|
||||
Matrix<T>::Copy(inv_xform_, rhs.inv_xform_);
|
||||
Matrix<T>::Copy(inv_xform33_, rhs.inv_xform33_);
|
||||
Matrix<T>::Copy(inv_transpose_xform33_, rhs.inv_transpose_xform33_);
|
||||
|
||||
lbmin_[0] = rhs.lbmin_[0];
|
||||
lbmin_[1] = rhs.lbmin_[1];
|
||||
lbmin_[2] = rhs.lbmin_[2];
|
||||
|
||||
lbmax_[0] = rhs.lbmax_[0];
|
||||
lbmax_[1] = rhs.lbmax_[1];
|
||||
lbmax_[2] = rhs.lbmax_[2];
|
||||
|
||||
xbmin_[0] = rhs.xbmin_[0];
|
||||
xbmin_[1] = rhs.xbmin_[1];
|
||||
xbmin_[2] = rhs.xbmin_[2];
|
||||
|
||||
xbmax_[0] = rhs.xbmax_[0];
|
||||
xbmax_[1] = rhs.xbmax_[1];
|
||||
xbmax_[2] = rhs.xbmax_[2];
|
||||
|
||||
mesh_ = rhs.mesh_;
|
||||
name_ = rhs.name_;
|
||||
|
||||
children_ = rhs.children_;
|
||||
}
|
||||
|
||||
Node(const type &rhs) {
|
||||
Copy(rhs);
|
||||
}
|
||||
|
||||
const type &operator=(const type &rhs) {
|
||||
Copy(rhs);
|
||||
return (*this);
|
||||
}
|
||||
|
||||
void SetName(const std::string &name) {
|
||||
name_ = name;
|
||||
}
|
||||
|
||||
const std::string &GetName() const {
|
||||
return name_;
|
||||
}
|
||||
|
||||
///
|
||||
/// Add child node.
|
||||
///
|
||||
void AddChild(const type &child) {
|
||||
children_.push_back(child);
|
||||
}
|
||||
|
||||
///
|
||||
/// Get chidren
|
||||
///
|
||||
const std::vector<type> &GetChildren() const {
|
||||
return children_;
|
||||
}
|
||||
|
||||
std::vector<type> &GetChildren() {
|
||||
return children_;
|
||||
}
|
||||
|
||||
///
|
||||
/// Update internal state.
|
||||
///
|
||||
void Update(const T parent_xform[4][4]) {
|
||||
|
||||
if (!accel_.IsValid() && mesh_ && (mesh_->vertices.size() > 3) && (mesh_->faces.size() >= 3)) {
|
||||
|
||||
// Assume mesh is composed of triangle faces only.
|
||||
nanort::TriangleMesh<float> triangle_mesh(mesh_->vertices.data(), mesh_->faces.data(), sizeof(float) * 3);
|
||||
nanort::TriangleSAHPred<float> triangle_pred(mesh_->vertices.data(), mesh_->faces.data(), sizeof(float) * 3);
|
||||
|
||||
bool ret = accel_.Build(int(mesh_->faces.size()) / 3, triangle_mesh, triangle_pred);
|
||||
|
||||
// Update local bbox.
|
||||
if (ret) {
|
||||
accel_.BoundingBox(lbmin_, lbmax_);
|
||||
}
|
||||
}
|
||||
|
||||
// xform = parent_xform x local_xform
|
||||
Matrix<T>::Mult(xform_, parent_xform, local_xform_);
|
||||
|
||||
// Compute the bounding box in world coordinate.
|
||||
XformBoundingBox(xbmin_, xbmax_, lbmin_, lbmax_, xform_);
|
||||
|
||||
// Inverse(xform)
|
||||
Matrix<T>::Copy(inv_xform_, xform_);
|
||||
Matrix<T>::Inverse(inv_xform_);
|
||||
|
||||
// Clear translation, then inverse(xform)
|
||||
Matrix<T>::Copy(inv_xform33_, xform_);
|
||||
inv_xform33_[3][0] = static_cast<T>(0.0);
|
||||
inv_xform33_[3][1] = static_cast<T>(0.0);
|
||||
inv_xform33_[3][2] = static_cast<T>(0.0);
|
||||
Matrix<T>::Inverse(inv_xform33_);
|
||||
|
||||
// Inverse transpose of xform33
|
||||
Matrix<T>::Copy(inv_transpose_xform33_, inv_xform33_);
|
||||
Matrix<T>::Transpose(inv_transpose_xform33_);
|
||||
|
||||
// Update children nodes
|
||||
for (size_t i = 0; i < children_.size(); i++) {
|
||||
children_[i].Update(xform_);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Set local transformation.
|
||||
///
|
||||
void SetLocalXform(const T xform[4][4]) {
|
||||
memcpy(local_xform_, xform, sizeof(float) * 16);
|
||||
}
|
||||
|
||||
const T *GetLocalXformPtr() const {
|
||||
return &local_xform_[0][0];
|
||||
}
|
||||
|
||||
const T *GetXformPtr() const {
|
||||
return &xform_[0][0];
|
||||
}
|
||||
|
||||
const M *GetMesh() const {
|
||||
return mesh_;
|
||||
}
|
||||
|
||||
const nanort::BVHAccel<T> &GetAccel() const {
|
||||
return accel_;
|
||||
}
|
||||
|
||||
inline void GetWorldBoundingBox(T bmin[3], T bmax[3]) const {
|
||||
bmin[0] = xbmin_[0];
|
||||
bmin[1] = xbmin_[1];
|
||||
bmin[2] = xbmin_[2];
|
||||
|
||||
bmax[0] = xbmax_[0];
|
||||
bmax[1] = xbmax_[1];
|
||||
bmax[2] = xbmax_[2];
|
||||
}
|
||||
|
||||
inline void GetLocalBoundingBox(T bmin[3], T bmax[3]) const {
|
||||
bmin[0] = lbmin_[0];
|
||||
bmin[1] = lbmin_[1];
|
||||
bmin[2] = lbmin_[2];
|
||||
|
||||
bmax[0] = lbmax_[0];
|
||||
bmax[1] = lbmax_[1];
|
||||
bmax[2] = lbmax_[2];
|
||||
}
|
||||
|
||||
T local_xform_[4][4]; // Node's local transformation matrix.
|
||||
T xform_[4][4]; // Parent xform x local_xform.
|
||||
T inv_xform_[4][4]; // inverse(xform). world -> local
|
||||
T inv_xform33_[4][4]; // inverse(xform0 with upper-left 3x3 elemets only(for transforming direction vector)
|
||||
T inv_transpose_xform33_[4][4]; // inverse(transpose(xform)) with upper-left 3x3 elements only(for transforming normal vector)
|
||||
|
||||
private:
|
||||
|
||||
// bounding box(local space)
|
||||
T lbmin_[3];
|
||||
T lbmax_[3];
|
||||
|
||||
// bounding box after xform(world space)
|
||||
T xbmin_[3];
|
||||
T xbmax_[3];
|
||||
|
||||
nanort::BVHAccel<T> accel_;
|
||||
|
||||
std::string name_;
|
||||
|
||||
const M *mesh_;
|
||||
|
||||
std::vector<type> children_;
|
||||
|
||||
};
|
||||
|
||||
// -------------------------------------------------
|
||||
|
||||
// Predefined SAH predicator for cube.
|
||||
template<typename T, class M>
|
||||
class NodeBBoxPred {
|
||||
public:
|
||||
NodeBBoxPred(const std::vector<Node<T, M> >* nodes) : axis_(0), pos_(0.0f), nodes_(nodes) {}
|
||||
|
||||
void Set(int axis, float pos) const {
|
||||
axis_ = axis;
|
||||
pos_ = pos;
|
||||
}
|
||||
|
||||
bool operator()(unsigned int i) const {
|
||||
int axis = axis_;
|
||||
float pos = pos_;
|
||||
|
||||
T bmin[3], bmax[3];
|
||||
|
||||
(*nodes_)[i].GetWorldBoundingBox(bmin, bmax);
|
||||
|
||||
T center = bmax[axis] - bmin[axis];
|
||||
|
||||
return (center < pos);
|
||||
}
|
||||
|
||||
private:
|
||||
mutable int axis_;
|
||||
mutable float pos_;
|
||||
const std::vector<Node<T, M> > *nodes_;
|
||||
};
|
||||
|
||||
template<typename T, class M>
|
||||
class NodeBBoxGeometry {
|
||||
public:
|
||||
NodeBBoxGeometry(const std::vector<Node<T, M> >* nodes)
|
||||
: nodes_(nodes) {}
|
||||
|
||||
/// Compute bounding box for `prim_index`th cube.
|
||||
/// This function is called for each primitive in BVH build.
|
||||
void BoundingBox(nanort::real3<T>* bmin, nanort::real3<T>* bmax, unsigned int prim_index) const {
|
||||
T a[3], b[3];
|
||||
(*nodes_)[prim_index].GetWorldBoundingBox(a, b);
|
||||
(*bmin)[0] = a[0];
|
||||
(*bmin)[1] = a[1];
|
||||
(*bmin)[2] = a[2];
|
||||
(*bmax)[0] = b[0];
|
||||
(*bmax)[1] = b[1];
|
||||
(*bmax)[2] = b[2];
|
||||
}
|
||||
|
||||
const std::vector<Node<T, M> >* nodes_;
|
||||
mutable nanort::real3<T> ray_org_;
|
||||
mutable nanort::real3<T> ray_dir_;
|
||||
mutable nanort::BVHTraceOptions trace_options_;
|
||||
};
|
||||
|
||||
class NodeBBoxIntersection {
|
||||
public:
|
||||
NodeBBoxIntersection() {}
|
||||
|
||||
float normal[3];
|
||||
|
||||
// Required member variables.
|
||||
float t;
|
||||
unsigned int prim_id;
|
||||
};
|
||||
|
||||
template<typename T, class M>
|
||||
class NodeBBoxIntersector {
|
||||
public:
|
||||
NodeBBoxIntersector(const std::vector<Node<T, M> >* nodes)
|
||||
: nodes_(nodes) {}
|
||||
|
||||
bool Intersect(float* out_t_min, float *out_t_max, unsigned int prim_index) const {
|
||||
|
||||
T bmin[3], bmax[3];
|
||||
|
||||
(*nodes_)[prim_index].GetWorldBoundingBox(bmin, bmax);
|
||||
|
||||
float tmin, tmax;
|
||||
|
||||
const float min_x = ray_dir_sign_[0] ? bmax[0] : bmin[0];
|
||||
const float min_y = ray_dir_sign_[1] ? bmax[1] : bmin[1];
|
||||
const float min_z = ray_dir_sign_[2] ? bmax[2] : bmin[2];
|
||||
const float max_x = ray_dir_sign_[0] ? bmin[0] : bmax[0];
|
||||
const float max_y = ray_dir_sign_[1] ? bmin[1] : bmax[1];
|
||||
const float max_z = ray_dir_sign_[2] ? bmin[2] : bmax[2];
|
||||
|
||||
// X
|
||||
const float tmin_x = (min_x - ray_org_[0]) * ray_inv_dir_[0];
|
||||
const float tmax_x = (max_x - ray_org_[0]) * ray_inv_dir_[0];
|
||||
|
||||
// Y
|
||||
const float tmin_y = (min_y - ray_org_[1]) * ray_inv_dir_[1];
|
||||
const float tmax_y = (max_y - ray_org_[1]) * ray_inv_dir_[1];
|
||||
|
||||
// Z
|
||||
const float tmin_z = (min_z - ray_org_[2]) * ray_inv_dir_[2];
|
||||
const float tmax_z = (max_z - ray_org_[2]) * ray_inv_dir_[2];
|
||||
|
||||
tmin = nanort::safemax(tmin_z, nanort::safemax(tmin_y, tmin_x));
|
||||
tmax = nanort::safemin(tmax_z, nanort::safemin(tmax_y, tmax_x));
|
||||
|
||||
if (tmin <= tmax) {
|
||||
(*out_t_min) = tmin;
|
||||
(*out_t_max) = tmax;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// Prepare BVH traversal(e.g. compute inverse ray direction)
|
||||
/// This function is called only once in BVH traversal.
|
||||
void PrepareTraversal(const nanort::Ray<float>& ray) const {
|
||||
ray_org_[0] = ray.org[0];
|
||||
ray_org_[1] = ray.org[1];
|
||||
ray_org_[2] = ray.org[2];
|
||||
|
||||
ray_dir_[0] = ray.dir[0];
|
||||
ray_dir_[1] = ray.dir[1];
|
||||
ray_dir_[2] = ray.dir[2];
|
||||
|
||||
// FIXME(syoyo): Consider zero div case.
|
||||
ray_inv_dir_[0] = static_cast<T>(1.0) / ray.dir[0];
|
||||
ray_inv_dir_[1] = static_cast<T>(1.0) / ray.dir[1];
|
||||
ray_inv_dir_[2] = static_cast<T>(1.0) / ray.dir[2];
|
||||
|
||||
ray_dir_sign_[0] = ray.dir[0] < static_cast<T>(0.0) ? static_cast<T>(1) : static_cast<T>(0);
|
||||
ray_dir_sign_[1] = ray.dir[1] < static_cast<T>(0.0) ? static_cast<T>(1) : static_cast<T>(0);
|
||||
ray_dir_sign_[2] = ray.dir[2] < static_cast<T>(0.0) ? static_cast<T>(1) : static_cast<T>(0);
|
||||
}
|
||||
|
||||
const std::vector<Node<T, M> >* nodes_;
|
||||
mutable nanort::real3<T> ray_org_;
|
||||
mutable nanort::real3<T> ray_dir_;
|
||||
mutable nanort::real3<T> ray_inv_dir_;
|
||||
mutable int ray_dir_sign_[3];
|
||||
};
|
||||
|
||||
template<typename T, class M>
|
||||
class Scene
|
||||
{
|
||||
public:
|
||||
Scene() {
|
||||
bmin_[0] = bmin_[1] = bmin_[2] = std::numeric_limits<T>::max();
|
||||
bmax_[0] = bmax_[1] = bmax_[2] = -std::numeric_limits<T>::max();
|
||||
}
|
||||
|
||||
~Scene() {};
|
||||
|
||||
///
|
||||
/// Add intersectable node to the scene.
|
||||
///
|
||||
bool AddNode(const Node<T, M> &node) {
|
||||
nodes_.push_back(node);
|
||||
return true;
|
||||
}
|
||||
|
||||
const std::vector<Node<T, M> > &GetNodes() const {
|
||||
return nodes_;
|
||||
}
|
||||
|
||||
bool FindNode(const std::string &name, Node<T, M> **found_node) {
|
||||
if (!found_node) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (name.empty()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Simple exhaustive search.
|
||||
for (size_t i = 0; i < nodes_.size(); i++) {
|
||||
if (FindNodeRecursive(name, &(nodes_[i]), found_node)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
///
|
||||
/// Commit the scene. Must be called before tracing rays into the scene.
|
||||
///
|
||||
bool Commit() {
|
||||
|
||||
// Update nodes.
|
||||
for (size_t i = 0; i < nodes_.size(); i++) {
|
||||
T ident[4][4];
|
||||
Matrix<T>::Identity(ident);
|
||||
|
||||
nodes_[i].Update(ident);
|
||||
}
|
||||
|
||||
// Build toplevel BVH.
|
||||
NodeBBoxGeometry<T, M> geom(&nodes_);
|
||||
NodeBBoxPred<T, M> pred(&nodes_);
|
||||
|
||||
// FIXME(LTE): Limit one leaf contains one node bbox primitive. This would work, but would be inefficient.
|
||||
// e.g. will miss some node when constructed BVH depth is larger than the value of BVHBuildOptions.
|
||||
// Implement more better and efficient BVH build and traverse for Toplevel BVH.
|
||||
nanort::BVHBuildOptions<T> build_options;
|
||||
build_options.min_leaf_primitives = 1;
|
||||
|
||||
bool ret = toplevel_accel_.Build(static_cast<unsigned int>(nodes_.size()), geom, pred, build_options);
|
||||
|
||||
nanort::BVHBuildStatistics stats = toplevel_accel_.GetStatistics();
|
||||
|
||||
//toplevel_accel_.Debug();
|
||||
|
||||
if (ret) {
|
||||
toplevel_accel_.BoundingBox(bmin_, bmax_);
|
||||
} else {
|
||||
// Set invalid bbox value.
|
||||
bmin_[0] = std::numeric_limits<T>::max();
|
||||
bmin_[1] = std::numeric_limits<T>::max();
|
||||
bmin_[2] = std::numeric_limits<T>::max();
|
||||
|
||||
bmax_[0] = -std::numeric_limits<T>::max();
|
||||
bmax_[1] = -std::numeric_limits<T>::max();
|
||||
bmax_[2] = -std::numeric_limits<T>::max();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
///
|
||||
/// Get the scene bounding box.
|
||||
///
|
||||
void GetBoundingBox(T bmin[3], T bmax[3]) const {
|
||||
bmin[0] = bmin_[0];
|
||||
bmin[1] = bmin_[1];
|
||||
bmin[2] = bmin_[2];
|
||||
|
||||
bmax[0] = bmax_[0];
|
||||
bmax[1] = bmax_[1];
|
||||
bmax[2] = bmax_[2];
|
||||
}
|
||||
|
||||
///
|
||||
/// Trace the ray into the scene.
|
||||
/// First find the intersection of nodes' bounding box using toplevel BVH.
|
||||
/// Then, trace into the hit node to find the intersection of the primitive.
|
||||
///
|
||||
template<class H>
|
||||
bool Traverse(nanort::Ray<T> &ray, H *isect, const bool cull_back_face = false) const {
|
||||
|
||||
if (!toplevel_accel_.IsValid()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
const int kMaxIntersections = 64;
|
||||
|
||||
bool has_hit = false;
|
||||
|
||||
NodeBBoxIntersector<T, M> isector(&nodes_);
|
||||
nanort::StackVector<nanort::NodeHit<T>, 128> node_hits;
|
||||
bool may_hit = toplevel_accel_.ListNodeIntersections(ray, kMaxIntersections, isector, &node_hits);
|
||||
|
||||
if (may_hit) {
|
||||
|
||||
T t_max = std::numeric_limits<T>::max();
|
||||
T t_nearest = t_max;
|
||||
|
||||
nanort::BVHTraceOptions trace_options;
|
||||
trace_options.cull_back_face = cull_back_face;
|
||||
|
||||
// Find actual intersection point.
|
||||
for (size_t i = 0; i < node_hits->size(); i++) {
|
||||
|
||||
// Early cull test.
|
||||
if (t_nearest < node_hits[i].t_min) {
|
||||
//printf("near: %f, t_min: %f, t_max: %f\n", t_nearest, node_hits[i].t_min, node_hits[i].t_max);
|
||||
continue;
|
||||
}
|
||||
|
||||
assert(node_hits[i].node_id < nodes_.size());
|
||||
const Node<T, M> &node = nodes_[node_hits[i].node_id];
|
||||
|
||||
// Transform ray into node's local space
|
||||
// TODO(LTE): Set ray tmin and tmax
|
||||
nanort::Ray<T> local_ray;
|
||||
Matrix<T>::MultV(local_ray.org, node.inv_xform_, ray.org);
|
||||
Matrix<T>::MultV(local_ray.dir, node.inv_xform33_, ray.dir);
|
||||
|
||||
nanort::TriangleIntersector<T, H> triangle_intersector(node.GetMesh()->vertices.data(), node.GetMesh()->faces.data(), sizeof(T) * 3);
|
||||
H local_isect;
|
||||
|
||||
bool hit = node.GetAccel().Traverse(local_ray, triangle_intersector, &local_isect);
|
||||
|
||||
if (hit) {
|
||||
// Calulcate hit distance in world coordiante.
|
||||
T local_P[3];
|
||||
local_P[0] = local_ray.org[0] + local_isect.t * local_ray.dir[0];
|
||||
local_P[1] = local_ray.org[1] + local_isect.t * local_ray.dir[1];
|
||||
local_P[2] = local_ray.org[2] + local_isect.t * local_ray.dir[2];
|
||||
|
||||
T world_P[3];
|
||||
Matrix<T>::MultV(world_P, node.xform_, local_P);
|
||||
|
||||
nanort::real3<T> po;
|
||||
po[0] = world_P[0] - ray.org[0];
|
||||
po[1] = world_P[1] - ray.org[1];
|
||||
po[2] = world_P[2] - ray.org[2];
|
||||
|
||||
float t_world = vlength(po);
|
||||
|
||||
if (t_world < t_nearest) {
|
||||
t_nearest = t_world;
|
||||
has_hit = true;
|
||||
//(*isect) = local_isect;
|
||||
isect->node_id = node_hits[i].node_id;
|
||||
isect->prim_id = local_isect.prim_id;
|
||||
isect->u = local_isect.u;
|
||||
isect->v = local_isect.v;
|
||||
|
||||
// TODO(LTE): Implement
|
||||
T Ng[3], Ns[3]; // geometric normal, shading normal.
|
||||
|
||||
node.GetMesh()->GetNormal(Ng, Ns, isect->prim_id, isect->u, isect->v);
|
||||
|
||||
// Convert position and normal into world coordinate.
|
||||
isect->t = t_world;
|
||||
Matrix<T>::MultV(isect->P, node.xform_, local_P);
|
||||
Matrix<T>::MultV(isect->Ng, node.inv_transpose_xform33_,
|
||||
Ng);
|
||||
Matrix<T>::MultV(isect->Ns, node.inv_transpose_xform33_,
|
||||
Ns);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return has_hit;
|
||||
|
||||
}
|
||||
|
||||
private:
|
||||
|
||||
///
|
||||
/// Find a node by name.
|
||||
///
|
||||
bool FindNodeRecursive(const std::string &name, Node<T, M> *root, Node<T, M> **found_node) {
|
||||
|
||||
if (root->GetName().compare(name) == 0) {
|
||||
(*found_node) = root;
|
||||
return true;
|
||||
}
|
||||
|
||||
// Simple exhaustive search.
|
||||
for (size_t i = 0; i < root->GetChildren().size(); i++) {
|
||||
if (FindNodeRecursive(name, &(root->GetChildren()[i]), found_node)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
// Scene bounding box.
|
||||
// Valid after calling `Commit()`.
|
||||
T bmin_[3];
|
||||
T bmax_[3];
|
||||
|
||||
// Toplevel BVH accel.
|
||||
nanort::BVHAccel<T> toplevel_accel_;
|
||||
std::vector<Node<T, M> > nodes_;
|
||||
};
|
||||
|
||||
} // namespace nanosg
|
||||
|
||||
#endif // NANOSG_H_
|
@ -1,109 +0,0 @@
|
||||
newoption {
|
||||
trigger = "asan",
|
||||
description = "Enable Address Sanitizer(gcc5+ ang clang only)"
|
||||
}
|
||||
|
||||
sources = {
|
||||
"main.cc",
|
||||
"render.cc",
|
||||
"render-config.cc",
|
||||
"gltf-loader.cc",
|
||||
"matrix.cc",
|
||||
"../common/trackball.cc",
|
||||
"../common/imgui/imgui.cpp",
|
||||
"../common/imgui/imgui_draw.cpp",
|
||||
"../common/imgui/imgui_impl_btgui.cpp",
|
||||
"../common/imgui/ImGuizmo.cpp",
|
||||
}
|
||||
|
||||
solution "RaytraceSolution"
|
||||
configurations { "Release", "Debug" }
|
||||
|
||||
if os.is("Windows") then
|
||||
platforms { "x64", "x32" }
|
||||
else
|
||||
platforms { "native", "x64", "x32" }
|
||||
end
|
||||
|
||||
|
||||
-- RootDir for OpenGLWindow
|
||||
projectRootDir = os.getcwd() .. "/../common/"
|
||||
dofile ("../common/findOpenGLGlewGlut.lua")
|
||||
initOpenGL()
|
||||
initGlew()
|
||||
|
||||
-- Use c++11
|
||||
flags { "c++11" }
|
||||
|
||||
-- A project defines one build target
|
||||
project "viwewer"
|
||||
kind "ConsoleApp"
|
||||
language "C++"
|
||||
files { sources }
|
||||
|
||||
includedirs { "./", "../../" }
|
||||
includedirs { "../common" }
|
||||
includedirs { "../common/imgui" }
|
||||
includedirs { "../common/glm" }
|
||||
--includedirs { "../common/nativefiledialog/src/include" }
|
||||
|
||||
if _OPTIONS['asan'] then
|
||||
buildoptions { "-fsanitize=address" }
|
||||
linkoptions { "-fsanitize=address" }
|
||||
end
|
||||
|
||||
if os.is("Windows") then
|
||||
flags { "FatalCompileWarnings" }
|
||||
warnings "Extra" -- /W4
|
||||
|
||||
defines { "NOMINMAX" }
|
||||
defines { "USE_NATIVEFILEDIALOG" }
|
||||
buildoptions { "/W4" } -- raise compile error level.
|
||||
files{
|
||||
"../common/OpenGLWindow/Win32OpenGLWindow.cpp",
|
||||
"../common/OpenGLWindow/Win32OpenGLWindow.h",
|
||||
"../common/OpenGLWindow/Win32Window.cpp",
|
||||
"../common/OpenGLWindow/Win32Window.h",
|
||||
}
|
||||
includedirs { "./../common/nativefiledialog/src/include" }
|
||||
files { "../common/nativefiledialog/src/nfd_common.c",
|
||||
"../common/nativefiledialog/src/nfd_win.cpp" }
|
||||
end
|
||||
if os.is("Linux") then
|
||||
files {
|
||||
"../common/OpenGLWindow/X11OpenGLWindow.cpp",
|
||||
"../common/OpenGLWindow/X11OpenGLWindows.h"
|
||||
}
|
||||
links {"X11", "pthread", "dl"}
|
||||
if _OPTIONS["with-gtk3nfd"] then
|
||||
defines { "USE_NATIVEFILEDIALOG" }
|
||||
includedirs { "./../common/nativefiledialog/src/include" }
|
||||
files { "../common/nativefiledialog/src/nfd_gtk.c",
|
||||
"../common/nativefiledialog/src/nfd_common.c"
|
||||
}
|
||||
buildoptions { "`pkg-config --cflags gtk+-3.0`" }
|
||||
linkoptions { "`pkg-config --libs gtk+-3.0`" }
|
||||
end
|
||||
end
|
||||
if os.is("MacOSX") then
|
||||
defines { "USE_NATIVEFILEDIALOG" }
|
||||
links {"Cocoa.framework"}
|
||||
files {
|
||||
"../common/OpenGLWindow/MacOpenGLWindow.h",
|
||||
"../common/OpenGLWindow/MacOpenGLWindow.mm",
|
||||
}
|
||||
includedirs { "./../common/nativefiledialog/src/include" }
|
||||
files { "../common/nativefiledialog/src/nfd_cocoa.m",
|
||||
"../common/nativefiledialog/src/nfd_common.c" }
|
||||
end
|
||||
|
||||
configuration "Debug"
|
||||
defines { "DEBUG" } -- -DDEBUG
|
||||
symbols "On"
|
||||
targetname "view_debug"
|
||||
|
||||
configuration "Release"
|
||||
-- defines { "NDEBUG" } -- -NDEBUG
|
||||
symbols "On"
|
||||
optimize "On"
|
||||
targetname "view"
|
@ -1,110 +0,0 @@
|
||||
#include "render-config.h"
|
||||
|
||||
#include "picojson.h"
|
||||
|
||||
#include <fstream>
|
||||
#include <istream>
|
||||
|
||||
namespace example {
|
||||
|
||||
bool LoadRenderConfig(example::RenderConfig* config, const char* filename) {
|
||||
std::ifstream is(filename);
|
||||
if (is.fail()) {
|
||||
std::cerr << "Cannot open " << filename << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
std::istream_iterator<char> input(is);
|
||||
std::string err;
|
||||
picojson::value v;
|
||||
input = picojson::parse(v, input, std::istream_iterator<char>(), &err);
|
||||
if (!err.empty()) {
|
||||
std::cerr << err << std::endl;
|
||||
}
|
||||
|
||||
if (!v.is<picojson::object>()) {
|
||||
std::cerr << "Not a JSON object" << std::endl;
|
||||
return false;
|
||||
}
|
||||
|
||||
picojson::object o = v.get<picojson::object>();
|
||||
|
||||
if (o.find("gltf_filename") != o.end()) {
|
||||
if (o["gltf_filename"].is<std::string>()) {
|
||||
config->gltf_filename = o["gltf_filename"].get<std::string>();
|
||||
}
|
||||
}
|
||||
|
||||
config->scene_scale = 1.0f;
|
||||
if (o.find("scene_scale") != o.end()) {
|
||||
if (o["scene_scale"].is<double>()) {
|
||||
config->scene_scale = static_cast<float>(o["scene_scale"].get<double>());
|
||||
}
|
||||
}
|
||||
|
||||
config->eye[0] = 0.0f;
|
||||
config->eye[1] = 0.0f;
|
||||
config->eye[2] = 5.0f;
|
||||
if (o.find("eye") != o.end()) {
|
||||
if (o["eye"].is<picojson::array>()) {
|
||||
picojson::array arr = o["eye"].get<picojson::array>();
|
||||
if (arr.size() == 3) {
|
||||
config->eye[0] = static_cast<float>(arr[0].get<double>());
|
||||
config->eye[1] = static_cast<float>(arr[1].get<double>());
|
||||
config->eye[2] = static_cast<float>(arr[2].get<double>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
config->up[0] = 0.0f;
|
||||
config->up[1] = 1.0f;
|
||||
config->up[2] = 0.0f;
|
||||
if (o.find("up") != o.end()) {
|
||||
if (o["up"].is<picojson::array>()) {
|
||||
picojson::array arr = o["up"].get<picojson::array>();
|
||||
if (arr.size() == 3) {
|
||||
config->up[0] = static_cast<float>(arr[0].get<double>());
|
||||
config->up[1] = static_cast<float>(arr[1].get<double>());
|
||||
config->up[2] = static_cast<float>(arr[2].get<double>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
config->look_at[0] = 0.0f;
|
||||
config->look_at[1] = 0.0f;
|
||||
config->look_at[2] = 0.0f;
|
||||
if (o.find("look_at") != o.end()) {
|
||||
if (o["look_at"].is<picojson::array>()) {
|
||||
picojson::array arr = o["look_at"].get<picojson::array>();
|
||||
if (arr.size() == 3) {
|
||||
config->look_at[0] = static_cast<float>(arr[0].get<double>());
|
||||
config->look_at[1] = static_cast<float>(arr[1].get<double>());
|
||||
config->look_at[2] = static_cast<float>(arr[2].get<double>());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
config->fov = 45.0f;
|
||||
if (o.find("fov") != o.end()) {
|
||||
if (o["fov"].is<double>()) {
|
||||
config->fov = static_cast<float>(o["fov"].get<double>());
|
||||
}
|
||||
}
|
||||
|
||||
config->width = 512;
|
||||
if (o.find("width") != o.end()) {
|
||||
if (o["width"].is<double>()) {
|
||||
config->width = static_cast<int>(o["width"].get<double>());
|
||||
}
|
||||
}
|
||||
|
||||
config->height = 512;
|
||||
if (o.find("height") != o.end()) {
|
||||
if (o["height"].is<double>()) {
|
||||
config->height = static_cast<int>(o["height"].get<double>());
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,41 +0,0 @@
|
||||
#ifndef RENDER_CONFIG_H
|
||||
#define RENDER_CONFIG_H
|
||||
|
||||
#include <string>
|
||||
|
||||
namespace example {
|
||||
|
||||
typedef struct {
|
||||
// framebuffer
|
||||
int width;
|
||||
int height;
|
||||
|
||||
// camera
|
||||
float eye[3];
|
||||
float up[3];
|
||||
float look_at[3];
|
||||
float fov; // vertical fov in degree.
|
||||
|
||||
// render pass
|
||||
int pass;
|
||||
int max_passes;
|
||||
|
||||
// For debugging. Array size = width * height * 4.
|
||||
float *normalImage;
|
||||
float *positionImage;
|
||||
float *depthImage;
|
||||
float *texcoordImage;
|
||||
float *varycoordImage;
|
||||
|
||||
// Scene input info
|
||||
std::string gltf_filename;
|
||||
float scene_scale;
|
||||
|
||||
} RenderConfig;
|
||||
|
||||
/// Loads config from JSON file.
|
||||
bool LoadRenderConfig(example::RenderConfig *config, const char *filename);
|
||||
|
||||
} // namespace
|
||||
|
||||
#endif // RENDER_CONFIG_H
|
@ -1,512 +0,0 @@
|
||||
/*
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 - 2016 Light Transport Entertainment, Inc.
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef _MSC_VER
|
||||
#pragma warning(disable : 4018)
|
||||
#pragma warning(disable : 4244)
|
||||
#pragma warning(disable : 4189)
|
||||
#pragma warning(disable : 4996)
|
||||
#pragma warning(disable : 4267)
|
||||
#pragma warning(disable : 4477)
|
||||
#endif
|
||||
|
||||
#include "render.h"
|
||||
|
||||
#include <chrono> // C++11
|
||||
#include <sstream>
|
||||
#include <thread> // C++11
|
||||
#include <vector>
|
||||
|
||||
#include <iostream>
|
||||
|
||||
#include "nanort.h"
|
||||
#include "matrix.h"
|
||||
#include "material.h"
|
||||
#include "mesh.h"
|
||||
|
||||
|
||||
#include "trackball.h"
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#undef min
|
||||
#undef max
|
||||
#endif
|
||||
|
||||
namespace example {
|
||||
|
||||
// PCG32 code / (c) 2014 M.E. O'Neill / pcg-random.org
|
||||
// Licensed under Apache License 2.0 (NO WARRANTY, etc. see website)
|
||||
// http://www.pcg-random.org/
|
||||
typedef struct {
|
||||
unsigned long long state;
|
||||
unsigned long long inc; // not used?
|
||||
} pcg32_state_t;
|
||||
|
||||
#define PCG32_INITIALIZER \
|
||||
{ 0x853c49e6748fea9bULL, 0xda3e39cb94b95bdbULL }
|
||||
|
||||
float pcg32_random(pcg32_state_t* rng) {
|
||||
unsigned long long oldstate = rng->state;
|
||||
rng->state = oldstate * 6364136223846793005ULL + rng->inc;
|
||||
unsigned int xorshifted = ((oldstate >> 18u) ^ oldstate) >> 27u;
|
||||
unsigned int rot = oldstate >> 59u;
|
||||
unsigned int ret = (xorshifted >> rot) | (xorshifted << ((-static_cast<int>(rot)) & 31));
|
||||
|
||||
return (float)((double)ret / (double)4294967296.0);
|
||||
}
|
||||
|
||||
void pcg32_srandom(pcg32_state_t* rng, uint64_t initstate, uint64_t initseq) {
|
||||
rng->state = 0U;
|
||||
rng->inc = (initseq << 1U) | 1U;
|
||||
pcg32_random(rng);
|
||||
rng->state += initstate;
|
||||
pcg32_random(rng);
|
||||
}
|
||||
|
||||
const float kPI = 3.141592f;
|
||||
|
||||
typedef nanort::real3<float> float3;
|
||||
|
||||
inline float3 Lerp3(float3 v0, float3 v1, float3 v2, float u, float v) {
|
||||
return (1.0f - u - v) * v0 + u * v1 + v * v2;
|
||||
}
|
||||
|
||||
inline void CalcNormal(float3& N, float3 v0, float3 v1, float3 v2) {
|
||||
float3 v10 = v1 - v0;
|
||||
float3 v20 = v2 - v0;
|
||||
|
||||
N = vcross(v20, v10);
|
||||
N = vnormalize(N);
|
||||
}
|
||||
|
||||
void BuildCameraFrame(float3* origin, float3* corner, float3* u, float3* v,
|
||||
float quat[4], float eye[3], float lookat[3], float up[3],
|
||||
float fov, int width, int height) {
|
||||
float e[4][4];
|
||||
|
||||
Matrix::LookAt(e, eye, lookat, up);
|
||||
|
||||
float r[4][4];
|
||||
build_rotmatrix(r, quat);
|
||||
|
||||
float3 lo;
|
||||
lo[0] = lookat[0] - eye[0];
|
||||
lo[1] = lookat[1] - eye[1];
|
||||
lo[2] = lookat[2] - eye[2];
|
||||
float dist = vlength(lo);
|
||||
|
||||
float dir[3];
|
||||
dir[0] = 0.0;
|
||||
dir[1] = 0.0;
|
||||
dir[2] = dist;
|
||||
|
||||
Matrix::Inverse(r);
|
||||
|
||||
float rr[4][4];
|
||||
float re[4][4];
|
||||
float zero[3] = {0.0f, 0.0f, 0.0f};
|
||||
float localUp[3] = {0.0f, 1.0f, 0.0f};
|
||||
Matrix::LookAt(re, dir, zero, localUp);
|
||||
|
||||
// translate
|
||||
re[3][0] += eye[0]; // 0.0; //lo[0];
|
||||
re[3][1] += eye[1]; // 0.0; //lo[1];
|
||||
re[3][2] += (eye[2] - dist);
|
||||
|
||||
// rot -> trans
|
||||
Matrix::Mult(rr, r, re);
|
||||
|
||||
float m[4][4];
|
||||
for (int j = 0; j < 4; j++) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
m[j][i] = rr[j][i];
|
||||
}
|
||||
}
|
||||
|
||||
float vzero[3] = {0.0f, 0.0f, 0.0f};
|
||||
float eye1[3];
|
||||
Matrix::MultV(eye1, m, vzero);
|
||||
|
||||
float lookat1d[3];
|
||||
dir[2] = -dir[2];
|
||||
Matrix::MultV(lookat1d, m, dir);
|
||||
float3 lookat1(lookat1d[0], lookat1d[1], lookat1d[2]);
|
||||
|
||||
float up1d[3];
|
||||
Matrix::MultV(up1d, m, up);
|
||||
|
||||
float3 up1(up1d[0], up1d[1], up1d[2]);
|
||||
|
||||
// absolute -> relative
|
||||
up1[0] -= eye1[0];
|
||||
up1[1] -= eye1[1];
|
||||
up1[2] -= eye1[2];
|
||||
// printf("up1(after) = %f, %f, %f\n", up1[0], up1[1], up1[2]);
|
||||
|
||||
// Use original up vector
|
||||
// up1[0] = up[0];
|
||||
// up1[1] = up[1];
|
||||
// up1[2] = up[2];
|
||||
|
||||
{
|
||||
float flen =
|
||||
(0.5f * (float)height / tanf(0.5f * (float)(fov * kPI / 180.0f)));
|
||||
float3 look1;
|
||||
look1[0] = lookat1[0] - eye1[0];
|
||||
look1[1] = lookat1[1] - eye1[1];
|
||||
look1[2] = lookat1[2] - eye1[2];
|
||||
// vcross(u, up1, look1);
|
||||
// flip
|
||||
(*u) = nanort::vcross(look1, up1);
|
||||
(*u) = vnormalize((*u));
|
||||
|
||||
(*v) = vcross(look1, (*u));
|
||||
(*v) = vnormalize((*v));
|
||||
|
||||
look1 = vnormalize(look1);
|
||||
look1[0] = flen * look1[0] + eye1[0];
|
||||
look1[1] = flen * look1[1] + eye1[1];
|
||||
look1[2] = flen * look1[2] + eye1[2];
|
||||
(*corner)[0] = look1[0] - 0.5f * (width * (*u)[0] + height * (*v)[0]);
|
||||
(*corner)[1] = look1[1] - 0.5f * (width * (*u)[1] + height * (*v)[1]);
|
||||
(*corner)[2] = look1[2] - 0.5f * (width * (*u)[2] + height * (*v)[2]);
|
||||
|
||||
(*origin)[0] = eye1[0];
|
||||
(*origin)[1] = eye1[1];
|
||||
(*origin)[2] = eye1[2];
|
||||
}
|
||||
}
|
||||
|
||||
nanort::Ray<float> GenerateRay(const float3& origin, const float3& corner,
|
||||
const float3& du, const float3& dv, float u,
|
||||
float v) {
|
||||
float3 dir;
|
||||
|
||||
dir[0] = (corner[0] + u * du[0] + v * dv[0]) - origin[0];
|
||||
dir[1] = (corner[1] + u * du[1] + v * dv[1]) - origin[1];
|
||||
dir[2] = (corner[2] + u * du[2] + v * dv[2]) - origin[2];
|
||||
dir = vnormalize(dir);
|
||||
|
||||
float3 org;
|
||||
|
||||
nanort::Ray<float> ray;
|
||||
ray.org[0] = origin[0];
|
||||
ray.org[1] = origin[1];
|
||||
ray.org[2] = origin[2];
|
||||
ray.dir[0] = dir[0];
|
||||
|
||||
return ray;
|
||||
}
|
||||
|
||||
void FetchTexture(const Texture &texture, float u, float v, float* col) {
|
||||
int tx = u * texture.width;
|
||||
int ty = (1.0f - v) * texture.height;
|
||||
int idx_offset = (ty * texture.width + tx) * texture.components;
|
||||
col[0] = texture.image[idx_offset + 0] / 255.f;
|
||||
col[1] = texture.image[idx_offset + 1] / 255.f;
|
||||
col[2] = texture.image[idx_offset + 2] / 255.f;
|
||||
}
|
||||
|
||||
bool Renderer::Render(float* rgba, float* aux_rgba, int* sample_counts,
|
||||
float quat[4],
|
||||
const nanosg::Scene<float, example::Mesh<float>> &scene,
|
||||
const example::Asset &asset,
|
||||
const RenderConfig& config,
|
||||
std::atomic<bool>& cancelFlag) {
|
||||
//if (!gAccel.IsValid()) {
|
||||
// return false;
|
||||
//}
|
||||
|
||||
int width = config.width;
|
||||
int height = config.height;
|
||||
|
||||
// camera
|
||||
float eye[3] = {config.eye[0], config.eye[1], config.eye[2]};
|
||||
float look_at[3] = {config.look_at[0], config.look_at[1], config.look_at[2]};
|
||||
float up[3] = {config.up[0], config.up[1], config.up[2]};
|
||||
float fov = config.fov;
|
||||
float3 origin, corner, u, v;
|
||||
BuildCameraFrame(&origin, &corner, &u, &v, quat, eye, look_at, up, fov, width,
|
||||
height);
|
||||
|
||||
auto kCancelFlagCheckMilliSeconds = 300;
|
||||
|
||||
std::vector<std::thread> workers;
|
||||
std::atomic<int> i(0);
|
||||
|
||||
uint32_t num_threads = std::max(1U, std::thread::hardware_concurrency());
|
||||
|
||||
auto startT = std::chrono::system_clock::now();
|
||||
|
||||
// Initialize RNG.
|
||||
|
||||
for (auto t = 0; t < num_threads; t++) {
|
||||
workers.emplace_back(std::thread([&, t]() {
|
||||
pcg32_state_t rng;
|
||||
pcg32_srandom(&rng, config.pass,
|
||||
t); // seed = combination of render pass + thread no.
|
||||
|
||||
int y = 0;
|
||||
while ((y = i++) < config.height) {
|
||||
auto currT = std::chrono::system_clock::now();
|
||||
|
||||
std::chrono::duration<double, std::milli> ms = currT - startT;
|
||||
// Check cancel flag
|
||||
if (ms.count() > kCancelFlagCheckMilliSeconds) {
|
||||
if (cancelFlag) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// draw dash line to aux buffer for progress.
|
||||
// for (int x = 0; x < config.width; x++) {
|
||||
// float c = (x / 8) % 2;
|
||||
// aux_rgba[4*(y*config.width+x)+0] = c;
|
||||
// aux_rgba[4*(y*config.width+x)+1] = c;
|
||||
// aux_rgba[4*(y*config.width+x)+2] = c;
|
||||
// aux_rgba[4*(y*config.width+x)+3] = 0.0f;
|
||||
//}
|
||||
|
||||
for (int x = 0; x < config.width; x++) {
|
||||
nanort::Ray<float> ray;
|
||||
ray.org[0] = origin[0];
|
||||
ray.org[1] = origin[1];
|
||||
ray.org[2] = origin[2];
|
||||
|
||||
float u0 = pcg32_random(&rng);
|
||||
float u1 = pcg32_random(&rng);
|
||||
|
||||
float3 dir;
|
||||
dir = corner + (float(x) + u0) * u +
|
||||
(float(config.height - y - 1) + u1) * v;
|
||||
dir = vnormalize(dir);
|
||||
ray.dir[0] = dir[0];
|
||||
ray.dir[1] = dir[1];
|
||||
ray.dir[2] = dir[2];
|
||||
|
||||
float kFar = 1.0e+30f;
|
||||
ray.min_t = 0.0f;
|
||||
ray.max_t = kFar;
|
||||
|
||||
|
||||
nanosg::Intersection<float> isect;
|
||||
bool hit = scene.Traverse(ray, &isect, /* cull_back_face */false);
|
||||
|
||||
if (hit) {
|
||||
|
||||
const std::vector<Material> &materials = asset.materials;
|
||||
const std::vector<Texture> &textures = asset.textures;
|
||||
const Mesh<float> &mesh = asset.meshes[isect.node_id];
|
||||
|
||||
float3 p;
|
||||
p[0] =
|
||||
ray.org[0] + isect.t * ray.dir[0];
|
||||
p[1] =
|
||||
ray.org[1] + isect.t * ray.dir[1];
|
||||
p[2] =
|
||||
ray.org[2] + isect.t * ray.dir[2];
|
||||
|
||||
config.positionImage[4 * (y * config.width + x) + 0] = p.x();
|
||||
config.positionImage[4 * (y * config.width + x) + 1] = p.y();
|
||||
config.positionImage[4 * (y * config.width + x) + 2] = p.z();
|
||||
config.positionImage[4 * (y * config.width + x) + 3] = 1.0f;
|
||||
|
||||
config.varycoordImage[4 * (y * config.width + x) + 0] =
|
||||
isect.u;
|
||||
config.varycoordImage[4 * (y * config.width + x) + 1] =
|
||||
isect.v;
|
||||
config.varycoordImage[4 * (y * config.width + x) + 2] = 0.0f;
|
||||
config.varycoordImage[4 * (y * config.width + x) + 3] = 1.0f;
|
||||
|
||||
unsigned int prim_id = isect.prim_id;
|
||||
|
||||
float3 N;
|
||||
if (mesh.facevarying_normals.size() > 0) {
|
||||
float3 n0, n1, n2;
|
||||
n0[0] = mesh.facevarying_normals[9 * prim_id + 0];
|
||||
n0[1] = mesh.facevarying_normals[9 * prim_id + 1];
|
||||
n0[2] = mesh.facevarying_normals[9 * prim_id + 2];
|
||||
n1[0] = mesh.facevarying_normals[9 * prim_id + 3];
|
||||
n1[1] = mesh.facevarying_normals[9 * prim_id + 4];
|
||||
n1[2] = mesh.facevarying_normals[9 * prim_id + 5];
|
||||
n2[0] = mesh.facevarying_normals[9 * prim_id + 6];
|
||||
n2[1] = mesh.facevarying_normals[9 * prim_id + 7];
|
||||
n2[2] = mesh.facevarying_normals[9 * prim_id + 8];
|
||||
N = Lerp3(n0, n1, n2, isect.u, isect.v);
|
||||
} else {
|
||||
unsigned int f0, f1, f2;
|
||||
f0 = mesh.faces[3 * prim_id + 0];
|
||||
f1 = mesh.faces[3 * prim_id + 1];
|
||||
f2 = mesh.faces[3 * prim_id + 2];
|
||||
|
||||
float3 v0, v1, v2;
|
||||
v0[0] = mesh.vertices[3 * f0 + 0];
|
||||
v0[1] = mesh.vertices[3 * f0 + 1];
|
||||
v0[2] = mesh.vertices[3 * f0 + 2];
|
||||
v1[0] = mesh.vertices[3 * f1 + 0];
|
||||
v1[1] = mesh.vertices[3 * f1 + 1];
|
||||
v1[2] = mesh.vertices[3 * f1 + 2];
|
||||
v2[0] = mesh.vertices[3 * f2 + 0];
|
||||
v2[1] = mesh.vertices[3 * f2 + 1];
|
||||
v2[2] = mesh.vertices[3 * f2 + 2];
|
||||
CalcNormal(N, v0, v1, v2);
|
||||
}
|
||||
|
||||
config.normalImage[4 * (y * config.width + x) + 0] =
|
||||
0.5f * N[0] + 0.5f;
|
||||
config.normalImage[4 * (y * config.width + x) + 1] =
|
||||
0.5f * N[1] + 0.5f;
|
||||
config.normalImage[4 * (y * config.width + x) + 2] =
|
||||
0.5f * N[2] + 0.5f;
|
||||
config.normalImage[4 * (y * config.width + x) + 3] = 1.0f;
|
||||
|
||||
config.depthImage[4 * (y * config.width + x) + 0] =
|
||||
isect.t;
|
||||
config.depthImage[4 * (y * config.width + x) + 1] =
|
||||
isect.t;
|
||||
config.depthImage[4 * (y * config.width + x) + 2] =
|
||||
isect.t;
|
||||
config.depthImage[4 * (y * config.width + x) + 3] = 1.0f;
|
||||
|
||||
float3 UV;
|
||||
if (mesh.facevarying_uvs.size() > 0) {
|
||||
float3 uv0, uv1, uv2;
|
||||
uv0[0] = mesh.facevarying_uvs[6 * prim_id + 0];
|
||||
uv0[1] = mesh.facevarying_uvs[6 * prim_id + 1];
|
||||
uv1[0] = mesh.facevarying_uvs[6 * prim_id + 2];
|
||||
uv1[1] = mesh.facevarying_uvs[6 * prim_id + 3];
|
||||
uv2[0] = mesh.facevarying_uvs[6 * prim_id + 4];
|
||||
uv2[1] = mesh.facevarying_uvs[6 * prim_id + 5];
|
||||
|
||||
UV = Lerp3(uv0, uv1, uv2, isect.u, isect.v);
|
||||
|
||||
config.texcoordImage[4 * (y * config.width + x) + 0] = UV[0];
|
||||
config.texcoordImage[4 * (y * config.width + x) + 1] = UV[1];
|
||||
}
|
||||
|
||||
// Fetch texture
|
||||
unsigned int material_id =
|
||||
mesh.material_ids[isect.prim_id];
|
||||
|
||||
float diffuse_col[3];
|
||||
int diffuse_texid = materials[material_id].diffuse_texid;
|
||||
if (diffuse_texid >= 0) {
|
||||
FetchTexture(textures[diffuse_texid], UV[0], UV[1], diffuse_col);
|
||||
} else {
|
||||
diffuse_col[0] = materials[material_id].diffuse[0];
|
||||
diffuse_col[1] = materials[material_id].diffuse[1];
|
||||
diffuse_col[2] = materials[material_id].diffuse[2];
|
||||
}
|
||||
|
||||
float specular_col[3];
|
||||
int specular_texid = materials[material_id].specular_texid;
|
||||
if (specular_texid >= 0) {
|
||||
FetchTexture(textures[specular_texid], UV[0], UV[1], specular_col);
|
||||
} else {
|
||||
specular_col[0] = materials[material_id].specular[0];
|
||||
specular_col[1] = materials[material_id].specular[1];
|
||||
specular_col[2] = materials[material_id].specular[2];
|
||||
}
|
||||
|
||||
// Simple shading
|
||||
float NdotV = fabsf(vdot(N, dir));
|
||||
|
||||
if (config.pass == 0) {
|
||||
rgba[4 * (y * config.width + x) + 0] = NdotV * diffuse_col[0];
|
||||
rgba[4 * (y * config.width + x) + 1] = NdotV * diffuse_col[1];
|
||||
rgba[4 * (y * config.width + x) + 2] = NdotV * diffuse_col[2];
|
||||
rgba[4 * (y * config.width + x) + 3] = 1.0f;
|
||||
sample_counts[y * config.width + x] =
|
||||
1; // Set 1 for the first pass
|
||||
} else { // additive.
|
||||
rgba[4 * (y * config.width + x) + 0] += NdotV * diffuse_col[0];
|
||||
rgba[4 * (y * config.width + x) + 1] += NdotV * diffuse_col[1];
|
||||
rgba[4 * (y * config.width + x) + 2] += NdotV * diffuse_col[2];
|
||||
rgba[4 * (y * config.width + x) + 3] += 1.0f;
|
||||
sample_counts[y * config.width + x]++;
|
||||
}
|
||||
|
||||
} else {
|
||||
{
|
||||
if (config.pass == 0) {
|
||||
// clear pixel
|
||||
rgba[4 * (y * config.width + x) + 0] = 0.0f;
|
||||
rgba[4 * (y * config.width + x) + 1] = 0.0f;
|
||||
rgba[4 * (y * config.width + x) + 2] = 0.0f;
|
||||
rgba[4 * (y * config.width + x) + 3] = 0.0f;
|
||||
aux_rgba[4 * (y * config.width + x) + 0] = 0.0f;
|
||||
aux_rgba[4 * (y * config.width + x) + 1] = 0.0f;
|
||||
aux_rgba[4 * (y * config.width + x) + 2] = 0.0f;
|
||||
aux_rgba[4 * (y * config.width + x) + 3] = 0.0f;
|
||||
sample_counts[y * config.width + x] =
|
||||
1; // Set 1 for the first pass
|
||||
} else {
|
||||
sample_counts[y * config.width + x]++;
|
||||
}
|
||||
|
||||
// No super sampling
|
||||
config.normalImage[4 * (y * config.width + x) + 0] = 0.0f;
|
||||
config.normalImage[4 * (y * config.width + x) + 1] = 0.0f;
|
||||
config.normalImage[4 * (y * config.width + x) + 2] = 0.0f;
|
||||
config.normalImage[4 * (y * config.width + x) + 3] = 0.0f;
|
||||
config.positionImage[4 * (y * config.width + x) + 0] = 0.0f;
|
||||
config.positionImage[4 * (y * config.width + x) + 1] = 0.0f;
|
||||
config.positionImage[4 * (y * config.width + x) + 2] = 0.0f;
|
||||
config.positionImage[4 * (y * config.width + x) + 3] = 0.0f;
|
||||
config.depthImage[4 * (y * config.width + x) + 0] = 0.0f;
|
||||
config.depthImage[4 * (y * config.width + x) + 1] = 0.0f;
|
||||
config.depthImage[4 * (y * config.width + x) + 2] = 0.0f;
|
||||
config.depthImage[4 * (y * config.width + x) + 3] = 0.0f;
|
||||
config.texcoordImage[4 * (y * config.width + x) + 0] = 0.0f;
|
||||
config.texcoordImage[4 * (y * config.width + x) + 1] = 0.0f;
|
||||
config.texcoordImage[4 * (y * config.width + x) + 2] = 0.0f;
|
||||
config.texcoordImage[4 * (y * config.width + x) + 3] = 0.0f;
|
||||
config.varycoordImage[4 * (y * config.width + x) + 0] = 0.0f;
|
||||
config.varycoordImage[4 * (y * config.width + x) + 1] = 0.0f;
|
||||
config.varycoordImage[4 * (y * config.width + x) + 2] = 0.0f;
|
||||
config.varycoordImage[4 * (y * config.width + x) + 3] = 0.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int x = 0; x < config.width; x++) {
|
||||
aux_rgba[4 * (y * config.width + x) + 0] = 0.0f;
|
||||
aux_rgba[4 * (y * config.width + x) + 1] = 0.0f;
|
||||
aux_rgba[4 * (y * config.width + x) + 2] = 0.0f;
|
||||
aux_rgba[4 * (y * config.width + x) + 3] = 0.0f;
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
for (auto& t : workers) {
|
||||
t.join();
|
||||
}
|
||||
|
||||
return (!cancelFlag);
|
||||
};
|
||||
|
||||
} // namespace example
|
@ -1,30 +0,0 @@
|
||||
#ifndef EXAMPLE_RENDER_H_
|
||||
#define EXAMPLE_RENDER_H_
|
||||
|
||||
#include <atomic> // C++11
|
||||
|
||||
#include "render-config.h"
|
||||
#include "nanosg.h"
|
||||
#include "mesh.h"
|
||||
#include "material.h"
|
||||
|
||||
namespace example {
|
||||
|
||||
struct Asset {
|
||||
std::vector<Mesh<float> > meshes;
|
||||
std::vector<Material> materials;
|
||||
std::vector<Texture> textures;
|
||||
};
|
||||
|
||||
class Renderer {
|
||||
public:
|
||||
Renderer() {}
|
||||
~Renderer() {}
|
||||
|
||||
/// Returns false when the rendering was canceled.
|
||||
static bool Render(float* rgba, float* aux_rgba, int *sample_counts, float quat[4],
|
||||
const nanosg::Scene<float, Mesh<float>> &scene, const Asset &asset, const RenderConfig& config, std::atomic<bool>& cancel_flag);
|
||||
};
|
||||
};
|
||||
|
||||
#endif // EXAMPLE_RENDER_H_
|
Loading…
x
Reference in New Issue
Block a user