#ifndef EXAMPLE_MESH_H_ #define EXAMPLE_MESH_H_ #include #include #include #include namespace example { template 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(1.0) - u - v) * v0[0] + u * v1[0] + v * v2[0]; dst[1] = (static_cast(1.0) - u - v) * v0[1] + u * v1[1] + v * v2[1]; dst[2] = (static_cast(1.0) - u - v) * v0[2] + u * v1[2] + v * v2[2]; } template 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::epsilon()) { return std::sqrt(d); } else { return static_cast(0.0); } } template 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::epsilon()) { const T inv_len = static_cast(1.0) / len; dst[0] *= inv_len; dst[1] *= inv_len; dst[2] *= inv_len; } } template 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 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 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 class Mesh { public: explicit Mesh(const size_t vertex_stride) : stride(vertex_stride) { } std::string name; std::vector vertices; /// stride * num_vertices std::vector facevarying_normals; /// [xyz] * 3(triangle) * num_faces std::vector facevarying_tangents; /// [xyz] * 3(triangle) * num_faces std::vector facevarying_binormals; /// [xyz] * 3(triangle) * num_faces std::vector facevarying_uvs; /// [xy] * 3(triangle) * num_faces std::vector facevarying_vertex_colors; /// [xyz] * 3(triangle) * num_faces std::vector faces; /// triangle x num_faces std::vector material_ids; /// index x num_faces T pivot_xform[4][4]; size_t stride; /// stride for vertex data. // --- 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(0.0); t1[0] = facevarying_uvs[6 * face_idx + 2]; t1[1] = facevarying_uvs[6 * face_idx + 3]; t1[2] = static_cast(0.0); t2[0] = facevarying_uvs[6 * face_idx + 4]; t2[1] = facevarying_uvs[6 * face_idx + 5]; t2[2] = static_cast(0.0); lerp(tcoord, t0, t1, t2, u, v); } else { tcoord[0] = static_cast(0.0); tcoord[1] = static_cast(0.0); tcoord[2] = static_cast(0.0); } } }; } // namespace example #endif // EXAMPLE_MESH_H_