// ======================================================================== // // Copyright 2009-2017 Intel Corporation // // // // Licensed under the Apache License, Version 2.0 (the "License"); // // you may not use this file except in compliance with the License. // // You may obtain a copy of the License at // // // // http://www.apache.org/licenses/LICENSE-2.0 // // // // Unless required by applicable law or agreed to in writing, software // // distributed under the License is distributed on an "AS IS" BASIS, // // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // // See the License for the specific language governing permissions and // // limitations under the License. // // ======================================================================== // #pragma once #include "primitive.h" namespace embree { /* Stores M triangles from an indexed face set */ template struct TriangleMi { typedef Vec3> Vec3vfM; /* Virtual interface to query information about the triangle type */ struct Type : public PrimitiveType { Type(); size_t size(const char* This) const; }; static Type type; public: /* Returns maximal number of stored triangles */ static __forceinline size_t max_size() { return M; } /* Returns required number of primitive blocks for N primitives */ static __forceinline size_t blocks(size_t N) { return (N+max_size()-1)/max_size(); } public: /* Default constructor */ __forceinline TriangleMi() { } /* Construction from vertices and IDs */ __forceinline TriangleMi(const vint& v0, const vint& v1, const vint& v2, const vint& geomIDs, const vint& primIDs) : v0(v0), v1(v1), v2(v2), geomIDs(geomIDs), primIDs(primIDs) {} /* Returns a mask that tells which triangles are valid */ __forceinline vbool valid() const { return primIDs != vint(-1); } /* Returns if the specified triangle is valid */ __forceinline bool valid(const size_t i) const { assert(i geomID() const { return geomIDs; } __forceinline int geomID(const size_t i) const { assert(i primID() const { return primIDs; } __forceinline int primID(const size_t i) const { assert(i>& p0, Vec3>& p1, Vec3>& p2, const Scene* const scene) const; /* Non temporal store */ __forceinline static void store_nt(TriangleMi* dst, const TriangleMi& src) { vint::store_nt(&dst->v0,src.v0); vint::store_nt(&dst->v1,src.v1); vint::store_nt(&dst->v2,src.v2); vint::store_nt(&dst->geomIDs,src.geomIDs); vint::store_nt(&dst->primIDs,src.primIDs); } /* Fill triangle from triangle list */ __forceinline void fill(const PrimRef* prims, size_t& begin, size_t end, Scene* scene) { vint geomID = -1, primID = -1; vint v0 = zero, v1 = zero, v2 = zero; const PrimRef* prim = &prims[begin]; for (size_t i=0; iget(prim->geomID()); const TriangleMesh::Triangle& tri = mesh->triangle(prim->primID()); if (begingeomID(); primID[i] = prim->primID(); int* base = (int*) mesh->vertexPtr(tri.v[0]); v0[i] = tri.v[0]; v1[i] = int(size_t((int*)mesh->vertexPtr(tri.v[1])-base)); v2[i] = int(size_t((int*)mesh->vertexPtr(tri.v[2])-base)); begin++; } else { assert(i); if (i > 0) { geomID[i] = geomID[0]; primID[i] = -1; v0[i] = 0; v1[i] = 0; v2[i] = 0; } } if (begintriangle(primId); const Vec3fa p0 = mesh->vertex(tri.v[0]); const Vec3fa p1 = mesh->vertex(tri.v[1]); const Vec3fa p2 = mesh->vertex(tri.v[2]); bounds.extend(merge(BBox3fa(p0),BBox3fa(p1),BBox3fa(p2))); } return bounds; } public: vint v0; // index to 1st vertex vint v1; // offset to 2nd vertex vint v2; // offset to 3rd vertex vint geomIDs; // geometry ID of mesh vint primIDs; // primitive ID of primitive inside mesh }; template<> __forceinline void TriangleMi<4>::gather(Vec3vf4& p0, Vec3vf4& p1, Vec3vf4& p2, const Scene* const scene) const { const bool samegeom = all(geomIDs == vint4(geomIDs[0])); if (likely(samegeom)) { const TriangleMesh* mesh = scene->get(geomIDs[0]); const int* base0 = (const int*) mesh->vertexPtr(v0[0]); const int* base1 = (const int*) mesh->vertexPtr(v0[1]); const int* base2 = (const int*) mesh->vertexPtr(v0[2]); const int* base3 = (const int*) mesh->vertexPtr(v0[3]); const vfloat4 a0 = vfloat4::loadu(base0 ), a1 = vfloat4::loadu(base1 ), a2 = vfloat4::loadu(base2 ), a3 = vfloat4::loadu(base3 ); const vfloat4 b0 = vfloat4::loadu(base0+v1[0]), b1 = vfloat4::loadu(base1+v1[1]), b2 = vfloat4::loadu(base2+v1[2]), b3 = vfloat4::loadu(base3+v1[3]); const vfloat4 c0 = vfloat4::loadu(base0+v2[0]), c1 = vfloat4::loadu(base1+v2[1]), c2 = vfloat4::loadu(base2+v2[2]), c3 = vfloat4::loadu(base3+v2[3]); transpose(a0,a1,a2,a3,p0.x,p0.y,p0.z); transpose(b0,b1,b2,b3,p1.x,p1.y,p1.z); transpose(c0,c1,c2,c3,p2.x,p2.y,p2.z); } else { const int* base0 = (const int*) scene->get(geomIDs[0])->vertexPtr(v0[0]); const int* base1 = (const int*) scene->get(geomIDs[1])->vertexPtr(v0[1]); const int* base2 = (const int*) scene->get(geomIDs[2])->vertexPtr(v0[2]); const int* base3 = (const int*) scene->get(geomIDs[3])->vertexPtr(v0[3]); const vfloat4 a0 = vfloat4::loadu(base0 ), a1 = vfloat4::loadu(base1 ), a2 = vfloat4::loadu(base2 ), a3 = vfloat4::loadu(base3 ); const vfloat4 b0 = vfloat4::loadu(base0+v1[0]), b1 = vfloat4::loadu(base1+v1[1]), b2 = vfloat4::loadu(base2+v1[2]), b3 = vfloat4::loadu(base3+v1[3]); const vfloat4 c0 = vfloat4::loadu(base0+v2[0]), c1 = vfloat4::loadu(base1+v2[1]), c2 = vfloat4::loadu(base2+v2[2]), c3 = vfloat4::loadu(base3+v2[3]); transpose(a0,a1,a2,a3,p0.x,p0.y,p0.z); transpose(b0,b1,b2,b3,p1.x,p1.y,p1.z); transpose(c0,c1,c2,c3,p2.x,p2.y,p2.z); } } template typename TriangleMi::Type TriangleMi::type; typedef TriangleMi<4> Triangle4i; }