Path: blob/master/thirdparty/embree/kernels/common/scene_triangle_mesh.h
9905 views
// Copyright 2009-2021 Intel Corporation1// SPDX-License-Identifier: Apache-2.023#pragma once45#include "geometry.h"6#include "buffer.h"78namespace embree9{10/*! Triangle Mesh */11struct TriangleMesh : public Geometry12{13/*! type of this geometry */14static const Geometry::GTypeMask geom_type = Geometry::MTY_TRIANGLE_MESH;1516/*! triangle indices */17struct Triangle18{19uint32_t v[3];2021/*! outputs triangle indices */22__forceinline friend embree_ostream operator<<(embree_ostream cout, const Triangle& t) {23return cout << "Triangle { " << t.v[0] << ", " << t.v[1] << ", " << t.v[2] << " }";24}25};2627public:2829/*! triangle mesh construction */30TriangleMesh (Device* device);3132/* geometry interface */33public:34virtual void setMask(unsigned mask) override;35virtual void setNumTimeSteps (unsigned int numTimeSteps) override;36virtual void setVertexAttributeCount (unsigned int N) override;37virtual void setBuffer(RTCBufferType type, unsigned int slot, RTCFormat format, const Ref<Buffer>& buffer, size_t offset, size_t stride, unsigned int num) override;38virtual void* getBufferData(RTCBufferType type, unsigned int slot, BufferDataPointerType pointerType) override;39virtual void updateBuffer(RTCBufferType type, unsigned int slot) override;40virtual void commit() override;41virtual bool verify() override;42virtual void interpolate(const RTCInterpolateArguments* const args) override;43virtual void addElementsToCount (GeometryCounts & counts) const override;44virtual size_t getGeometryDataDeviceByteSize() const override;45virtual void convertToDeviceRepresentation(size_t offset, char* data_host, char* data_device) const override;4647template<int N>48void interpolate_impl(const RTCInterpolateArguments* const args)49{50unsigned int primID = args->primID;51float u = args->u;52float v = args->v;53RTCBufferType bufferType = args->bufferType;54unsigned int bufferSlot = args->bufferSlot;55float* P = args->P;56float* dPdu = args->dPdu;57float* dPdv = args->dPdv;58float* ddPdudu = args->ddPdudu;59float* ddPdvdv = args->ddPdvdv;60float* ddPdudv = args->ddPdudv;61unsigned int valueCount = args->valueCount;6263/* calculate base pointer and stride */64assert((bufferType == RTC_BUFFER_TYPE_VERTEX && bufferSlot < numTimeSteps) ||65(bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE && bufferSlot <= vertexAttribs.size()));66const char* src = nullptr;67size_t stride = 0;68if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE) {69src = vertexAttribs[bufferSlot].getPtr();70stride = vertexAttribs[bufferSlot].getStride();71} else {72src = vertices[bufferSlot].getPtr();73stride = vertices[bufferSlot].getStride();74}7576for (unsigned int i=0; i<valueCount; i+=N)77{78size_t ofs = i*sizeof(float);79const float w = 1.0f-u-v;80const Triangle& tri = triangle(primID);81const vbool<N> valid = vint<N>((int)i)+vint<N>(step) < vint<N>(int(valueCount));82const vfloat<N> p0 = mem<vfloat<N>>::loadu(valid,(float*)&src[tri.v[0]*stride+ofs]);83const vfloat<N> p1 = mem<vfloat<N>>::loadu(valid,(float*)&src[tri.v[1]*stride+ofs]);84const vfloat<N> p2 = mem<vfloat<N>>::loadu(valid,(float*)&src[tri.v[2]*stride+ofs]);8586if (P) {87mem<vfloat<N>>::storeu(valid,P+i,madd(w,p0,madd(u,p1,v*p2)));88}89if (dPdu) {90assert(dPdu); mem<vfloat<N>>::storeu(valid,dPdu+i,p1-p0);91assert(dPdv); mem<vfloat<N>>::storeu(valid,dPdv+i,p2-p0);92}93if (ddPdudu) {94assert(ddPdudu); mem<vfloat<N>>::storeu(valid,ddPdudu+i,vfloat<N>(zero));95assert(ddPdvdv); mem<vfloat<N>>::storeu(valid,ddPdvdv+i,vfloat<N>(zero));96assert(ddPdudv); mem<vfloat<N>>::storeu(valid,ddPdudv+i,vfloat<N>(zero));97}98}99}100101public:102103/*! returns number of vertices */104__forceinline size_t numVertices() const {105return vertices[0].size();106}107108/*! returns i'th triangle*/109__forceinline const Triangle& triangle(size_t i) const {110return triangles[i];111}112113/*! returns i'th vertex of the first time step */114__forceinline const Vec3fa vertex(size_t i) const {115return vertices0[i];116}117118/*! returns i'th vertex of the first time step */119__forceinline const char* vertexPtr(size_t i) const {120return vertices0.getPtr(i);121}122123/*! returns i'th vertex of itime'th timestep */124__forceinline const Vec3fa vertex(size_t i, size_t itime) const {125return vertices[itime][i];126}127128/*! returns i'th vertex of itime'th timestep */129__forceinline const char* vertexPtr(size_t i, size_t itime) const {130return vertices[itime].getPtr(i);131}132133/*! returns i'th vertex of for specified time */134__forceinline Vec3fa vertex(size_t i, float time) const135{136float ftime;137const size_t itime = timeSegment(time, ftime);138const float t0 = 1.0f - ftime;139const float t1 = ftime;140Vec3fa v0 = vertex(i, itime+0);141Vec3fa v1 = vertex(i, itime+1);142return madd(Vec3fa(t0),v0,t1*v1);143}144145/*! calculates the bounds of the i'th triangle */146__forceinline BBox3fa bounds(size_t i) const147{148const Triangle& tri = triangle(i);149const Vec3fa v0 = vertex(tri.v[0]);150const Vec3fa v1 = vertex(tri.v[1]);151const Vec3fa v2 = vertex(tri.v[2]);152return BBox3fa(min(v0,v1,v2),max(v0,v1,v2));153}154155/*! calculates the bounds of the i'th triangle at the itime'th timestep */156__forceinline BBox3fa bounds(size_t i, size_t itime) const157{158const Triangle& tri = triangle(i);159const Vec3fa v0 = vertex(tri.v[0],itime);160const Vec3fa v1 = vertex(tri.v[1],itime);161const Vec3fa v2 = vertex(tri.v[2],itime);162return BBox3fa(min(v0,v1,v2),max(v0,v1,v2));163}164165/*! check if the i'th primitive is valid at the itime'th timestep */166__forceinline bool valid(size_t i, size_t itime) const {167return valid(i, make_range(itime, itime));168}169170/*! check if the i'th primitive is valid between the specified time range */171__forceinline bool valid(size_t i, const range<size_t>& itime_range) const172{173const Triangle& tri = triangle(i);174if (unlikely(tri.v[0] >= numVertices())) return false;175if (unlikely(tri.v[1] >= numVertices())) return false;176if (unlikely(tri.v[2] >= numVertices())) return false;177178for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)179{180if (!isvalid(vertex(tri.v[0],itime))) return false;181if (!isvalid(vertex(tri.v[1],itime))) return false;182if (!isvalid(vertex(tri.v[2],itime))) return false;183}184185return true;186}187188/*! calculates the linear bounds of the i'th primitive at the itimeGlobal'th time segment */189__forceinline LBBox3fa linearBounds(size_t i, size_t itime) const {190return LBBox3fa(bounds(i,itime+0),bounds(i,itime+1));191}192193/*! calculates the build bounds of the i'th primitive, if it's valid */194__forceinline bool buildBounds(size_t i, BBox3fa* bbox = nullptr) const195{196const Triangle& tri = triangle(i);197if (unlikely(tri.v[0] >= numVertices())) return false;198if (unlikely(tri.v[1] >= numVertices())) return false;199if (unlikely(tri.v[2] >= numVertices())) return false;200201for (size_t t=0; t<numTimeSteps; t++)202{203const Vec3fa v0 = vertex(tri.v[0],t);204const Vec3fa v1 = vertex(tri.v[1],t);205const Vec3fa v2 = vertex(tri.v[2],t);206if (unlikely(!isvalid(v0) || !isvalid(v1) || !isvalid(v2)))207return false;208}209210if (likely(bbox))211*bbox = bounds(i);212213return true;214}215216/*! calculates the build bounds of the i'th primitive at the itime'th time segment, if it's valid */217__forceinline bool buildBounds(size_t i, size_t itime, BBox3fa& bbox) const218{219const Triangle& tri = triangle(i);220if (unlikely(tri.v[0] >= numVertices())) return false;221if (unlikely(tri.v[1] >= numVertices())) return false;222if (unlikely(tri.v[2] >= numVertices())) return false;223224assert(itime+1 < numTimeSteps);225const Vec3fa a0 = vertex(tri.v[0],itime+0); if (unlikely(!isvalid(a0))) return false;226const Vec3fa a1 = vertex(tri.v[1],itime+0); if (unlikely(!isvalid(a1))) return false;227const Vec3fa a2 = vertex(tri.v[2],itime+0); if (unlikely(!isvalid(a2))) return false;228const Vec3fa b0 = vertex(tri.v[0],itime+1); if (unlikely(!isvalid(b0))) return false;229const Vec3fa b1 = vertex(tri.v[1],itime+1); if (unlikely(!isvalid(b1))) return false;230const Vec3fa b2 = vertex(tri.v[2],itime+1); if (unlikely(!isvalid(b2))) return false;231232/* use bounds of first time step in builder */233bbox = BBox3fa(min(a0,a1,a2),max(a0,a1,a2));234return true;235}236237/*! calculates the linear bounds of the i'th primitive for the specified time range */238__forceinline LBBox3fa linearBounds(size_t primID, const BBox1f& dt) const {239return LBBox3fa([&] (size_t itime) { return bounds(primID, itime); }, dt, time_range, fnumTimeSegments);240}241242/*! calculates the linear bounds of the i'th primitive for the specified time range */243__forceinline bool linearBounds(size_t i, const BBox1f& dt, LBBox3fa& bbox) const {244if (!valid(i, timeSegmentRange(dt))) return false;245bbox = linearBounds(i, dt);246return true;247}248249/*! get fast access to first vertex buffer */250__forceinline float * getCompactVertexArray () const override {251return (float*) vertices0.getPtr();252}253254/* gets version info of topology */255unsigned int getTopologyVersion() const {256return triangles.modCounter;257}258259/* returns true if topology changed */260bool topologyChanged(unsigned int otherVersion) const {261return triangles.isModified(otherVersion); // || numPrimitivesChanged;262}263264/* returns the projected area */265__forceinline float projectedPrimitiveArea(const size_t i) const {266const Triangle& tri = triangle(i);267const Vec3fa v0 = vertex(tri.v[0]);268const Vec3fa v1 = vertex(tri.v[1]);269const Vec3fa v2 = vertex(tri.v[2]);270return areaProjectedTriangle(v0,v1,v2);271}272273public:274BufferView<Triangle> triangles; //!< array of triangles275BufferView<Vec3fa> vertices0; //!< fast access to first vertex buffer276Device::vector<BufferView<Vec3fa>> vertices = device; //!< vertex array for each timestep277Device::vector<RawBufferView> vertexAttribs = device; //!< vertex attributes278};279280namespace isa281{282struct TriangleMeshISA : public TriangleMesh283{284TriangleMeshISA (Device* device)285: TriangleMesh(device) {}286287#if !defined(__SYCL_DEVICE_ONLY__)288LBBox3fa vlinearBounds(size_t primID, const BBox1f& time_range) const {289return linearBounds(primID,time_range);290}291292PrimInfo createPrimRefArray(PrimRef* prims, const range<size_t>& r, size_t k, unsigned int geomID) const293{294PrimInfo pinfo(empty);295for (size_t j=r.begin(); j<r.end(); j++)296{297BBox3fa bounds = empty;298if (!buildBounds(j,&bounds)) continue;299const PrimRef prim(bounds,geomID,unsigned(j));300pinfo.add_center2(prim);301prims[k++] = prim;302}303return pinfo;304}305306PrimInfo createPrimRefArrayMB(mvector<PrimRef>& prims, size_t itime, const range<size_t>& r, size_t k, unsigned int geomID) const307{308PrimInfo pinfo(empty);309for (size_t j=r.begin(); j<r.end(); j++)310{311BBox3fa bounds = empty;312if (!buildBounds(j,itime,bounds)) continue;313const PrimRef prim(bounds,geomID,unsigned(j));314pinfo.add_center2(prim);315prims[k++] = prim;316}317return pinfo;318}319320PrimInfo createPrimRefArrayMB(PrimRef* prims, const BBox1f& time_range, const range<size_t>& r, size_t k, unsigned int geomID) const321{322PrimInfo pinfo(empty);323const BBox1f t0t1 = BBox1f::intersect(getTimeRange(), time_range);324if (t0t1.empty()) return pinfo;325326for (size_t j = r.begin(); j < r.end(); j++) {327LBBox3fa lbounds = empty;328if (!linearBounds(j, t0t1, lbounds))329continue;330const PrimRef prim(lbounds.bounds(), geomID, unsigned(j));331pinfo.add_center2(prim);332prims[k++] = prim;333}334return pinfo;335}336337PrimInfoMB createPrimRefMBArray(mvector<PrimRefMB>& prims, const BBox1f& t0t1, const range<size_t>& r, size_t k, unsigned int geomID) const338{339PrimInfoMB pinfo(empty);340for (size_t j=r.begin(); j<r.end(); j++)341{342if (!valid(j, timeSegmentRange(t0t1))) continue;343const PrimRefMB prim(linearBounds(j,t0t1),this->numTimeSegments(),this->time_range,this->numTimeSegments(),geomID,unsigned(j));344pinfo.add_primref(prim);345prims[k++] = prim;346}347return pinfo;348}349#endif350};351}352353DECLARE_ISA_FUNCTION(TriangleMesh*, createTriangleMesh, Device*);354}355356357