Path: blob/master/thirdparty/embree/kernels/common/scene_curves.h
9905 views
// Copyright 2009-2021 Intel Corporation1// SPDX-License-Identifier: Apache-2.023#pragma once45#include "default.h"6#include "geometry.h"7#include "buffer.h"89#include "../subdiv/bezier_curve.h"10#include "../subdiv/hermite_curve.h"11#include "../subdiv/bspline_curve.h"12#include "../subdiv/catmullrom_curve.h"13#include "../subdiv/linear_bezier_patch.h"1415namespace embree16{17/*! represents an array of bicubic bezier curves */18struct CurveGeometry : public Geometry19{20/*! type of this geometry */21static const Geometry::GTypeMask geom_type = Geometry::MTY_CURVE4;2223public:2425/*! bezier curve construction */26CurveGeometry (Device* device, Geometry::GType gtype);2728public:29void setMask(unsigned mask);30void setNumTimeSteps (unsigned int numTimeSteps);31void setVertexAttributeCount (unsigned int N);32void setBuffer(RTCBufferType type, unsigned int slot, RTCFormat format, const Ref<Buffer>& buffer, size_t offset, size_t stride, unsigned int num);33void* getBufferData(RTCBufferType type, unsigned int slot, BufferDataPointerType pointerType);34void updateBuffer(RTCBufferType type, unsigned int slot);35void commit();36bool verify();37void setTessellationRate(float N);38void setMaxRadiusScale(float s);39void addElementsToCount (GeometryCounts & counts) const;40size_t getGeometryDataDeviceByteSize() const;41void convertToDeviceRepresentation(size_t offset, char* data_host, char* data_device) const;4243public:4445/*! returns the number of vertices */46__forceinline size_t numVertices() const {47return vertices[0].size();48}4950/*! returns the i'th curve */51__forceinline const unsigned int& curve(size_t i) const {52return curves[i];53}5455/*! returns i'th vertex of the first time step */56__forceinline Vec3ff vertex(size_t i) const {57return vertices0[i];58}5960/*! returns i'th normal of the first time step */61__forceinline Vec3fa normal(size_t i) const {62return normals0[i];63}6465/*! returns i'th tangent of the first time step */66__forceinline Vec3ff tangent(size_t i) const {67return tangents0[i];68}6970/*! returns i'th normal derivative of the first time step */71__forceinline Vec3fa dnormal(size_t i) const {72return dnormals0[i];73}7475/*! returns i'th radius of the first time step */76__forceinline float radius(size_t i) const {77return vertices0[i].w;78}7980/*! returns i'th vertex of itime'th timestep */81__forceinline Vec3ff vertex(size_t i, size_t itime) const {82return vertices[itime][i];83}8485/*! returns i'th normal of itime'th timestep */86__forceinline Vec3fa normal(size_t i, size_t itime) const {87return normals[itime][i];88}8990/*! returns i'th tangent of itime'th timestep */91__forceinline Vec3ff tangent(size_t i, size_t itime) const {92return tangents[itime][i];93}9495/*! returns i'th normal derivative of itime'th timestep */96__forceinline Vec3fa dnormal(size_t i, size_t itime) const {97return dnormals[itime][i];98}99100/*! returns i'th radius of itime'th timestep */101__forceinline float radius(size_t i, size_t itime) const {102return vertices[itime][i].w;103}104105/*! gathers the curve starting with i'th vertex */106__forceinline void gather(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, size_t i) const107{108p0 = vertex(i+0);109p1 = vertex(i+1);110p2 = vertex(i+2);111p3 = vertex(i+3);112}113114/*! gathers the curve starting with i'th vertex of itime'th timestep */115__forceinline void gather(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, size_t i, size_t itime) const116{117p0 = vertex(i+0,itime);118p1 = vertex(i+1,itime);119p2 = vertex(i+2,itime);120p3 = vertex(i+3,itime);121}122123/*! gathers the curve normals starting with i'th vertex */124__forceinline void gather_normals(Vec3fa& n0, Vec3fa& n1, Vec3fa& n2, Vec3fa& n3, size_t i) const125{126n0 = normal(i+0);127n1 = normal(i+1);128n2 = normal(i+2);129n3 = normal(i+3);130}131132/*! gathers the curve starting with i'th vertex */133__forceinline void gather(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, Vec3fa& n0, Vec3fa& n1, Vec3fa& n2, Vec3fa& n3, size_t i) const134{135p0 = vertex(i+0);136p1 = vertex(i+1);137p2 = vertex(i+2);138p3 = vertex(i+3);139n0 = normal(i+0);140n1 = normal(i+1);141n2 = normal(i+2);142n3 = normal(i+3);143}144145/*! gathers the curve starting with i'th vertex of itime'th timestep */146__forceinline void gather(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, Vec3fa& n0, Vec3fa& n1, Vec3fa& n2, Vec3fa& n3, size_t i, size_t itime) const147{148p0 = vertex(i+0,itime);149p1 = vertex(i+1,itime);150p2 = vertex(i+2,itime);151p3 = vertex(i+3,itime);152n0 = normal(i+0,itime);153n1 = normal(i+1,itime);154n2 = normal(i+2,itime);155n3 = normal(i+3,itime);156}157158/*! prefetches the curve starting with i'th vertex of itime'th timestep */159__forceinline void prefetchL1_vertices(size_t i) const160{161prefetchL1(vertices0.getPtr(i)+0);162prefetchL1(vertices0.getPtr(i)+64);163}164165/*! prefetches the curve starting with i'th vertex of itime'th timestep */166__forceinline void prefetchL2_vertices(size_t i) const167{168prefetchL2(vertices0.getPtr(i)+0);169prefetchL2(vertices0.getPtr(i)+64);170}171172/*! loads curve vertices for specified time */173__forceinline void gather(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, size_t i, float time) const174{175float ftime;176const size_t itime = timeSegment(time, ftime);177178const float t0 = 1.0f - ftime;179const float t1 = ftime;180Vec3ff a0,a1,a2,a3;181gather(a0,a1,a2,a3,i,itime);182Vec3ff b0,b1,b2,b3;183gather(b0,b1,b2,b3,i,itime+1);184p0 = madd(Vec3ff(t0),a0,t1*b0);185p1 = madd(Vec3ff(t0),a1,t1*b1);186p2 = madd(Vec3ff(t0),a2,t1*b2);187p3 = madd(Vec3ff(t0),a3,t1*b3);188}189190/*! loads curve vertices for specified time */191__forceinline void gather_safe(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, size_t i, float time) const192{193if (hasMotionBlur()) gather(p0,p1,p2,p3,i,time);194else gather(p0,p1,p2,p3,i);195}196197/*! loads curve vertices for specified time */198__forceinline void gather(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, Vec3fa& n0, Vec3fa& n1, Vec3fa& n2, Vec3fa& n3, size_t i, float time) const199{200float ftime;201const size_t itime = timeSegment(time, ftime);202203const float t0 = 1.0f - ftime;204const float t1 = ftime;205Vec3ff a0,a1,a2,a3; Vec3fa an0,an1,an2,an3;206gather(a0,a1,a2,a3,an0,an1,an2,an3,i,itime);207Vec3ff b0,b1,b2,b3; Vec3fa bn0,bn1,bn2,bn3;208gather(b0,b1,b2,b3,bn0,bn1,bn2,bn3,i,itime+1);209p0 = madd(Vec3ff(t0),a0,t1*b0);210p1 = madd(Vec3ff(t0),a1,t1*b1);211p2 = madd(Vec3ff(t0),a2,t1*b2);212p3 = madd(Vec3ff(t0),a3,t1*b3);213n0 = madd(Vec3ff(t0),an0,t1*bn0);214n1 = madd(Vec3ff(t0),an1,t1*bn1);215n2 = madd(Vec3ff(t0),an2,t1*bn2);216n3 = madd(Vec3ff(t0),an3,t1*bn3);217}218219/*! loads curve vertices for specified time for mblur and non-mblur case */220__forceinline void gather_safe(Vec3ff& p0, Vec3ff& p1, Vec3ff& p2, Vec3ff& p3, Vec3fa& n0, Vec3fa& n1, Vec3fa& n2, Vec3fa& n3, size_t i, float time) const221{222if (hasMotionBlur()) gather(p0,p1,p2,p3,n0,n1,n2,n3,i,time);223else gather(p0,p1,p2,p3,n0,n1,n2,n3,i);224}225226template<typename SourceCurve3ff, typename SourceCurve3fa, typename TensorLinearCubicBezierSurface3fa>227__forceinline TensorLinearCubicBezierSurface3fa getNormalOrientedCurve(RayQueryContext* context, const Vec3fa& ray_org, const unsigned int primID, const size_t itime) const228{229Vec3ff v0,v1,v2,v3; Vec3fa n0,n1,n2,n3;230unsigned int vertexID = curve(primID);231gather(v0,v1,v2,v3,n0,n1,n2,n3,vertexID,itime);232SourceCurve3ff ccurve(v0,v1,v2,v3);233SourceCurve3fa ncurve(n0,n1,n2,n3);234ccurve = enlargeRadiusToMinWidth(context,this,ray_org,ccurve);235return TensorLinearCubicBezierSurface3fa::fromCenterAndNormalCurve(ccurve,ncurve);236}237238template<typename SourceCurve3ff, typename SourceCurve3fa, typename TensorLinearCubicBezierSurface3fa>239__forceinline TensorLinearCubicBezierSurface3fa getNormalOrientedCurve(RayQueryContext* context, const Vec3fa& ray_org, const unsigned int primID, const float time) const240{241float ftime;242const size_t itime = timeSegment(time, ftime);243const TensorLinearCubicBezierSurface3fa curve0 = getNormalOrientedCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context,ray_org,primID,itime+0);244const TensorLinearCubicBezierSurface3fa curve1 = getNormalOrientedCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context,ray_org,primID,itime+1);245return clerp(curve0,curve1,ftime);246}247248template<typename SourceCurve3ff, typename SourceCurve3fa, typename TensorLinearCubicBezierSurface3fa>249__forceinline TensorLinearCubicBezierSurface3fa getNormalOrientedCurveSafe(RayQueryContext* context, const Vec3fa& ray_org, const unsigned int primID, const float time) const250{251float ftime = 0.0f;252const size_t itime = hasMotionBlur() ? timeSegment(time, ftime) : 0;253const TensorLinearCubicBezierSurface3fa curve0 = getNormalOrientedCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context,ray_org,primID,itime+0);254if (hasMotionBlur()) {255const TensorLinearCubicBezierSurface3fa curve1 = getNormalOrientedCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context,ray_org,primID,itime+1);256return clerp(curve0,curve1,ftime);257}258return curve0;259}260261/*! gathers the hermite curve starting with i'th vertex */262__forceinline void gather_hermite(Vec3ff& p0, Vec3ff& t0, Vec3ff& p1, Vec3ff& t1, size_t i) const263{264p0 = vertex (i+0);265p1 = vertex (i+1);266t0 = tangent(i+0);267t1 = tangent(i+1);268}269270/*! gathers the hermite curve starting with i'th vertex of itime'th timestep */271__forceinline void gather_hermite(Vec3ff& p0, Vec3ff& t0, Vec3ff& p1, Vec3ff& t1, size_t i, size_t itime) const272{273p0 = vertex (i+0,itime);274p1 = vertex (i+1,itime);275t0 = tangent(i+0,itime);276t1 = tangent(i+1,itime);277}278279/*! loads curve vertices for specified time */280__forceinline void gather_hermite(Vec3ff& p0, Vec3ff& t0, Vec3ff& p1, Vec3ff& t1, size_t i, float time) const281{282float ftime;283const size_t itime = timeSegment(time, ftime);284const float f0 = 1.0f - ftime, f1 = ftime;285Vec3ff ap0,at0,ap1,at1;286gather_hermite(ap0,at0,ap1,at1,i,itime);287Vec3ff bp0,bt0,bp1,bt1;288gather_hermite(bp0,bt0,bp1,bt1,i,itime+1);289p0 = madd(Vec3ff(f0),ap0,f1*bp0);290t0 = madd(Vec3ff(f0),at0,f1*bt0);291p1 = madd(Vec3ff(f0),ap1,f1*bp1);292t1 = madd(Vec3ff(f0),at1,f1*bt1);293}294295/*! loads curve vertices for specified time for mblur and non-mblur geometry */296__forceinline void gather_hermite_safe(Vec3ff& p0, Vec3ff& t0, Vec3ff& p1, Vec3ff& t1, size_t i, float time) const297{298if (hasMotionBlur()) gather_hermite(p0,t0,p1,t1,i,time);299else gather_hermite(p0,t0,p1,t1,i);300}301302/*! gathers the hermite curve starting with i'th vertex */303__forceinline void gather_hermite(Vec3ff& p0, Vec3ff& t0, Vec3fa& n0, Vec3fa& dn0, Vec3ff& p1, Vec3ff& t1, Vec3fa& n1, Vec3fa& dn1, size_t i) const304{305p0 = vertex (i+0);306p1 = vertex (i+1);307t0 = tangent(i+0);308t1 = tangent(i+1);309n0 = normal(i+0);310n1 = normal(i+1);311dn0 = dnormal(i+0);312dn1 = dnormal(i+1);313}314315/*! gathers the hermite curve starting with i'th vertex of itime'th timestep */316__forceinline void gather_hermite(Vec3ff& p0, Vec3ff& t0, Vec3fa& n0, Vec3fa& dn0, Vec3ff& p1, Vec3ff& t1, Vec3fa& n1, Vec3fa& dn1, size_t i, size_t itime) const317{318p0 = vertex (i+0,itime);319p1 = vertex (i+1,itime);320t0 = tangent(i+0,itime);321t1 = tangent(i+1,itime);322n0 = normal(i+0,itime);323n1 = normal(i+1,itime);324dn0 = dnormal(i+0,itime);325dn1 = dnormal(i+1,itime);326}327328/*! loads curve vertices for specified time */329__forceinline void gather_hermite(Vec3ff& p0, Vec3ff& t0, Vec3fa& n0, Vec3fa& dn0, Vec3ff& p1, Vec3ff& t1, Vec3fa& n1, Vec3fa& dn1, size_t i, float time) const330{331float ftime;332const size_t itime = timeSegment(time, ftime);333const float f0 = 1.0f - ftime, f1 = ftime;334Vec3ff ap0,at0,ap1,at1; Vec3fa an0,adn0,an1,adn1;335gather_hermite(ap0,at0,an0,adn0,ap1,at1,an1,adn1,i,itime);336Vec3ff bp0,bt0,bp1,bt1; Vec3fa bn0,bdn0,bn1,bdn1;337gather_hermite(bp0,bt0,bn0,bdn0,bp1,bt1,bn1,bdn1,i,itime+1);338p0 = madd(Vec3ff(f0),ap0,f1*bp0);339t0 = madd(Vec3ff(f0),at0,f1*bt0);340n0 = madd(Vec3ff(f0),an0,f1*bn0);341dn0= madd(Vec3ff(f0),adn0,f1*bdn0);342p1 = madd(Vec3ff(f0),ap1,f1*bp1);343t1 = madd(Vec3ff(f0),at1,f1*bt1);344n1 = madd(Vec3ff(f0),an1,f1*bn1);345dn1= madd(Vec3ff(f0),adn1,f1*bdn1);346}347348/*! loads curve vertices for specified time */349__forceinline void gather_hermite_safe(Vec3ff& p0, Vec3ff& t0, Vec3fa& n0, Vec3fa& dn0, Vec3ff& p1, Vec3ff& t1, Vec3fa& n1, Vec3fa& dn1, size_t i, float time) const350{351if (hasMotionBlur()) gather_hermite(p0,t0,n0,dn0,p1,t1,n1,dn1,i,time);352else gather_hermite(p0,t0,n0,dn0,p1,t1,n1,dn1,i);353}354355template<typename SourceCurve3ff, typename SourceCurve3fa, typename TensorLinearCubicBezierSurface3fa>356__forceinline TensorLinearCubicBezierSurface3fa getNormalOrientedHermiteCurve(RayQueryContext* context, const Vec3fa& ray_org, const unsigned int primID, const size_t itime) const357{358Vec3ff v0,t0,v1,t1; Vec3fa n0,dn0,n1,dn1;359unsigned int vertexID = curve(primID);360gather_hermite(v0,t0,n0,dn0,v1,t1,n1,dn1,vertexID,itime);361362SourceCurve3ff ccurve(v0,t0,v1,t1);363SourceCurve3fa ncurve(n0,dn0,n1,dn1);364ccurve = enlargeRadiusToMinWidth(context,this,ray_org,ccurve);365return TensorLinearCubicBezierSurface3fa::fromCenterAndNormalCurve(ccurve,ncurve);366}367368template<typename SourceCurve3ff, typename SourceCurve3fa, typename TensorLinearCubicBezierSurface3fa>369__forceinline TensorLinearCubicBezierSurface3fa getNormalOrientedHermiteCurve(RayQueryContext* context, const Vec3fa& ray_org, const unsigned int primID, const float time) const370{371float ftime;372const size_t itime = timeSegment(time, ftime);373const TensorLinearCubicBezierSurface3fa curve0 = getNormalOrientedHermiteCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray_org, primID,itime+0);374const TensorLinearCubicBezierSurface3fa curve1 = getNormalOrientedHermiteCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray_org, primID,itime+1);375return clerp(curve0,curve1,ftime);376}377378template<typename SourceCurve3ff, typename SourceCurve3fa, typename TensorLinearCubicBezierSurface3fa>379__forceinline TensorLinearCubicBezierSurface3fa getNormalOrientedHermiteCurveSafe(RayQueryContext* context, const Vec3fa& ray_org, const unsigned int primID, const float time) const380{381float ftime = 0.0f;382const size_t itime = hasMotionBlur() ? timeSegment(time, ftime) : 0;383const TensorLinearCubicBezierSurface3fa curve0 = getNormalOrientedHermiteCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray_org, primID,itime+0);384if (hasMotionBlur()) {385const TensorLinearCubicBezierSurface3fa curve1 = getNormalOrientedHermiteCurve<SourceCurve3ff, SourceCurve3fa, TensorLinearCubicBezierSurface3fa>(context, ray_org, primID,itime+1);386return clerp(curve0,curve1,ftime);387}388return curve0;389}390391/* returns the projected area */392__forceinline float projectedPrimitiveArea(const size_t i) const {393return 1.0f;394}395396private:397void resizeBuffers(unsigned int numSteps);398399public:400BufferView<unsigned int> curves; //!< array of curve indices401BufferView<Vec3ff> vertices0; //!< fast access to first vertex buffer402BufferView<Vec3fa> normals0; //!< fast access to first normal buffer403BufferView<Vec3ff> tangents0; //!< fast access to first tangent buffer404BufferView<Vec3fa> dnormals0; //!< fast access to first normal derivative buffer405Device::vector<BufferView<Vec3ff>> vertices = device; //!< vertex array for each timestep406Device::vector<BufferView<Vec3fa>> normals = device; //!< normal array for each timestep407Device::vector<BufferView<Vec3ff>> tangents = device; //!< tangent array for each timestep408Device::vector<BufferView<Vec3fa>> dnormals = device; //!< normal derivative array for each timestep409BufferView<char> flags; //!< start, end flag per segment410Device::vector<BufferView<char>> vertexAttribs = device; //!< user buffers411int tessellationRate; //!< tessellation rate for flat curve412float maxRadiusScale = 1.0; //!< maximal min-width scaling of curve radii413};414415namespace isa416{417418template<template<typename Ty> class Curve>419struct CurveGeometryInterface : public CurveGeometry420{421typedef Curve<Vec3ff> Curve3ff;422typedef Curve<Vec3fa> Curve3fa;423424CurveGeometryInterface (Device* device, Geometry::GType gtype)425: CurveGeometry(device,gtype) {}426427__forceinline const Curve3ff getCurveScaledRadius(size_t i, size_t itime = 0) const428{429const unsigned int index = curve(i);430Vec3ff v0 = vertex(index+0,itime);431Vec3ff v1 = vertex(index+1,itime);432Vec3ff v2 = vertex(index+2,itime);433Vec3ff v3 = vertex(index+3,itime);434v0.w *= maxRadiusScale;435v1.w *= maxRadiusScale;436v2.w *= maxRadiusScale;437v3.w *= maxRadiusScale;438return Curve3ff (v0,v1,v2,v3);439}440441__forceinline const Curve3ff getCurveScaledRadius(const LinearSpace3fa& space, size_t i, size_t itime = 0) const442{443const unsigned int index = curve(i);444const Vec3ff v0 = vertex(index+0,itime);445const Vec3ff v1 = vertex(index+1,itime);446const Vec3ff v2 = vertex(index+2,itime);447const Vec3ff v3 = vertex(index+3,itime);448const Vec3ff w0(xfmPoint(space,(Vec3fa)v0), maxRadiusScale*v0.w);449const Vec3ff w1(xfmPoint(space,(Vec3fa)v1), maxRadiusScale*v1.w);450const Vec3ff w2(xfmPoint(space,(Vec3fa)v2), maxRadiusScale*v2.w);451const Vec3ff w3(xfmPoint(space,(Vec3fa)v3), maxRadiusScale*v3.w);452return Curve3ff(w0,w1,w2,w3);453}454455__forceinline const Curve3ff getCurveScaledRadius(const Vec3fa& ofs, const float scale, const float r_scale0, const LinearSpace3fa& space, size_t i, size_t itime = 0) const456{457const float r_scale = r_scale0*scale;458const unsigned int index = curve(i);459const Vec3ff v0 = vertex(index+0,itime);460const Vec3ff v1 = vertex(index+1,itime);461const Vec3ff v2 = vertex(index+2,itime);462const Vec3ff v3 = vertex(index+3,itime);463const Vec3ff w0(xfmPoint(space,((Vec3fa)v0-ofs)*Vec3fa(scale)), maxRadiusScale*v0.w*r_scale);464const Vec3ff w1(xfmPoint(space,((Vec3fa)v1-ofs)*Vec3fa(scale)), maxRadiusScale*v1.w*r_scale);465const Vec3ff w2(xfmPoint(space,((Vec3fa)v2-ofs)*Vec3fa(scale)), maxRadiusScale*v2.w*r_scale);466const Vec3ff w3(xfmPoint(space,((Vec3fa)v3-ofs)*Vec3fa(scale)), maxRadiusScale*v3.w*r_scale);467return Curve3ff(w0,w1,w2,w3);468}469470__forceinline const Curve3fa getNormalCurve(size_t i, size_t itime = 0) const471{472const unsigned int index = curve(i);473const Vec3fa n0 = normal(index+0,itime);474const Vec3fa n1 = normal(index+1,itime);475const Vec3fa n2 = normal(index+2,itime);476const Vec3fa n3 = normal(index+3,itime);477return Curve3fa (n0,n1,n2,n3);478}479480__forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(size_t i, size_t itime = 0) const481{482const Curve3ff center = getCurveScaledRadius(i,itime);483const Curve3fa normal = getNormalCurve(i,itime);484const TensorLinearCubicBezierSurface3fa ocurve = TensorLinearCubicBezierSurface3fa::fromCenterAndNormalCurve(center,normal);485return ocurve;486}487488__forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(const LinearSpace3fa& space, size_t i, size_t itime = 0) const {489return getOrientedCurveScaledRadius(i,itime).xfm(space);490}491492__forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(const Vec3fa& ofs, const float scale, const LinearSpace3fa& space, size_t i, size_t itime = 0) const {493return getOrientedCurveScaledRadius(i,itime).xfm(space,ofs,scale);494}495496/*! check if the i'th primitive is valid at the itime'th time step */497__forceinline bool valid(Geometry::GType ctype, size_t i, const range<size_t>& itime_range) const498{499const unsigned int index = curve(i);500if (index+3 >= numVertices()) return false;501502for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)503{504const float r0 = radius(index+0,itime);505const float r1 = radius(index+1,itime);506const float r2 = radius(index+2,itime);507const float r3 = radius(index+3,itime);508if (!isvalid(r0) || !isvalid(r1) || !isvalid(r2) || !isvalid(r3))509return false;510511const Vec3fa v0 = vertex(index+0,itime);512const Vec3fa v1 = vertex(index+1,itime);513const Vec3fa v2 = vertex(index+2,itime);514const Vec3fa v3 = vertex(index+3,itime);515if (!isvalid(v0) || !isvalid(v1) || !isvalid(v2) || !isvalid(v3))516return false;517518if (ctype == Geometry::GTY_SUBTYPE_ORIENTED_CURVE)519{520const Vec3fa n0 = normal(index+0,itime);521const Vec3fa n1 = normal(index+1,itime);522if (!isvalid(n0) || !isvalid(n1))523return false;524525const BBox3fa b = getOrientedCurveScaledRadius(i,itime).accurateBounds();526if (!isvalid(b))527return false;528}529}530531return true;532}533534template<int N>535void interpolate_impl(const RTCInterpolateArguments* const args)536{537unsigned int primID = args->primID;538float u = args->u;539RTCBufferType bufferType = args->bufferType;540unsigned int bufferSlot = args->bufferSlot;541float* P = args->P;542float* dPdu = args->dPdu;543float* ddPdudu = args->ddPdudu;544unsigned int valueCount = args->valueCount;545546/* calculate base pointer and stride */547assert((bufferType == RTC_BUFFER_TYPE_VERTEX && bufferSlot < numTimeSteps) ||548(bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE && bufferSlot <= vertexAttribs.size()));549const char* src = nullptr;550size_t stride = 0;551if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE) {552src = vertexAttribs[bufferSlot].getPtr();553stride = vertexAttribs[bufferSlot].getStride();554} else {555src = vertices[bufferSlot].getPtr();556stride = vertices[bufferSlot].getStride();557}558559for (unsigned int i=0; i<valueCount; i+=N)560{561size_t ofs = i*sizeof(float);562const size_t index = curves[primID];563const vbool<N> valid = vint<N>((int)i)+vint<N>(step) < vint<N>((int)valueCount);564const vfloat<N> p0 = mem<vfloat<N>>::loadu(valid,(float*)&src[(index+0)*stride+ofs]);565const vfloat<N> p1 = mem<vfloat<N>>::loadu(valid,(float*)&src[(index+1)*stride+ofs]);566const vfloat<N> p2 = mem<vfloat<N>>::loadu(valid,(float*)&src[(index+2)*stride+ofs]);567const vfloat<N> p3 = mem<vfloat<N>>::loadu(valid,(float*)&src[(index+3)*stride+ofs]);568569const Curve<vfloat<N>> curve(p0,p1,p2,p3);570if (P ) mem<vfloat<N>>::storeu(valid,P+i, curve.eval(u));571if (dPdu ) mem<vfloat<N>>::storeu(valid,dPdu+i, curve.eval_du(u));572if (ddPdudu) mem<vfloat<N>>::storeu(valid,ddPdudu+i,curve.eval_dudu(u));573}574}575576void interpolate(const RTCInterpolateArguments* const args) {577interpolate_impl<4>(args);578}579};580581template<template<typename Ty> class Curve>582struct HermiteCurveGeometryInterface : public CurveGeometry583{584typedef Curve<Vec3ff> HermiteCurve3ff;585typedef Curve<Vec3fa> HermiteCurve3fa;586587HermiteCurveGeometryInterface (Device* device, Geometry::GType gtype)588: CurveGeometry(device,gtype) {}589590__forceinline const HermiteCurve3ff getCurveScaledRadius(size_t i, size_t itime = 0) const591{592const unsigned int index = curve(i);593Vec3ff v0 = vertex(index+0,itime);594Vec3ff v1 = vertex(index+1,itime);595Vec3ff t0 = tangent(index+0,itime);596Vec3ff t1 = tangent(index+1,itime);597v0.w *= maxRadiusScale;598v1.w *= maxRadiusScale;599t0.w *= maxRadiusScale;600t1.w *= maxRadiusScale;601return HermiteCurve3ff (v0,t0,v1,t1);602}603604__forceinline const HermiteCurve3ff getCurveScaledRadius(const LinearSpace3fa& space, size_t i, size_t itime = 0) const605{606const unsigned int index = curve(i);607const Vec3ff v0 = vertex(index+0,itime);608const Vec3ff v1 = vertex(index+1,itime);609const Vec3ff t0 = tangent(index+0,itime);610const Vec3ff t1 = tangent(index+1,itime);611const Vec3ff V0(xfmPoint(space,(Vec3fa)v0),maxRadiusScale*v0.w);612const Vec3ff V1(xfmPoint(space,(Vec3fa)v1),maxRadiusScale*v1.w);613const Vec3ff T0(xfmVector(space,(Vec3fa)t0),maxRadiusScale*t0.w);614const Vec3ff T1(xfmVector(space,(Vec3fa)t1),maxRadiusScale*t1.w);615return HermiteCurve3ff(V0,T0,V1,T1);616}617618__forceinline const HermiteCurve3ff getCurveScaledRadius(const Vec3fa& ofs, const float scale, const float r_scale0, const LinearSpace3fa& space, size_t i, size_t itime = 0) const619{620const float r_scale = r_scale0*scale;621const unsigned int index = curve(i);622const Vec3ff v0 = vertex(index+0,itime);623const Vec3ff v1 = vertex(index+1,itime);624const Vec3ff t0 = tangent(index+0,itime);625const Vec3ff t1 = tangent(index+1,itime);626const Vec3ff V0(xfmPoint(space,(v0-ofs)*Vec3fa(scale)), maxRadiusScale*v0.w*r_scale);627const Vec3ff V1(xfmPoint(space,(v1-ofs)*Vec3fa(scale)), maxRadiusScale*v1.w*r_scale);628const Vec3ff T0(xfmVector(space,t0*Vec3fa(scale)), maxRadiusScale*t0.w*r_scale);629const Vec3ff T1(xfmVector(space,t1*Vec3fa(scale)), maxRadiusScale*t1.w*r_scale);630return HermiteCurve3ff(V0,T0,V1,T1);631}632633__forceinline const HermiteCurve3fa getNormalCurve(size_t i, size_t itime = 0) const634{635const unsigned int index = curve(i);636const Vec3fa n0 = normal(index+0,itime);637const Vec3fa n1 = normal(index+1,itime);638const Vec3fa dn0 = dnormal(index+0,itime);639const Vec3fa dn1 = dnormal(index+1,itime);640return HermiteCurve3fa (n0,dn0,n1,dn1);641}642643__forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(size_t i, size_t itime = 0) const644{645const HermiteCurve3ff center = getCurveScaledRadius(i,itime);646const HermiteCurve3fa normal = getNormalCurve(i,itime);647const TensorLinearCubicBezierSurface3fa ocurve = TensorLinearCubicBezierSurface3fa::fromCenterAndNormalCurve(center,normal);648return ocurve;649}650651__forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(const LinearSpace3fa& space, size_t i, size_t itime = 0) const {652return getOrientedCurveScaledRadius(i,itime).xfm(space);653}654655__forceinline const TensorLinearCubicBezierSurface3fa getOrientedCurveScaledRadius(const Vec3fa& ofs, const float scale, const LinearSpace3fa& space, size_t i, size_t itime = 0) const {656return getOrientedCurveScaledRadius(i,itime).xfm(space,ofs,scale);657}658659/*! check if the i'th primitive is valid at the itime'th time step */660__forceinline bool valid(Geometry::GType ctype, size_t i, const range<size_t>& itime_range) const661{662const unsigned int index = curve(i);663if (index+1 >= numVertices()) return false;664665for (size_t itime = itime_range.begin(); itime <= itime_range.end(); itime++)666{667const Vec3ff v0 = vertex(index+0,itime);668const Vec3ff v1 = vertex(index+1,itime);669if (!isvalid4(v0) || !isvalid4(v1))670return false;671672const Vec3ff t0 = tangent(index+0,itime);673const Vec3ff t1 = tangent(index+1,itime);674if (!isvalid4(t0) || !isvalid4(t1))675return false;676677if (ctype == Geometry::GTY_SUBTYPE_ORIENTED_CURVE)678{679const Vec3fa n0 = normal(index+0,itime);680const Vec3fa n1 = normal(index+1,itime);681if (!isvalid(n0) || !isvalid(n1))682return false;683684const Vec3fa dn0 = dnormal(index+0,itime);685const Vec3fa dn1 = dnormal(index+1,itime);686if (!isvalid(dn0) || !isvalid(dn1))687return false;688689const BBox3fa b = getOrientedCurveScaledRadius(i,itime).accurateBounds();690if (!isvalid(b))691return false;692}693}694695return true;696}697698template<int N>699void interpolate_impl(const RTCInterpolateArguments* const args)700{701unsigned int primID = args->primID;702float u = args->u;703RTCBufferType bufferType = args->bufferType;704unsigned int bufferSlot = args->bufferSlot;705float* P = args->P;706float* dPdu = args->dPdu;707float* ddPdudu = args->ddPdudu;708unsigned int valueCount = args->valueCount;709710/* we interpolate vertex attributes linearly for hermite basis */711if (bufferType == RTC_BUFFER_TYPE_VERTEX_ATTRIBUTE)712{713assert(bufferSlot <= vertexAttribs.size());714const char* vsrc = vertexAttribs[bufferSlot].getPtr();715const size_t vstride = vertexAttribs[bufferSlot].getStride();716717for (unsigned int i=0; i<valueCount; i+=N)718{719const size_t ofs = i*sizeof(float);720const size_t index = curves[primID];721const vbool<N> valid = vint<N>((int)i)+vint<N>(step) < vint<N>((int)valueCount);722const vfloat<N> p0 = mem<vfloat<N>>::loadu(valid,(float*)&vsrc[(index+0)*vstride+ofs]);723const vfloat<N> p1 = mem<vfloat<N>>::loadu(valid,(float*)&vsrc[(index+1)*vstride+ofs]);724725if (P ) mem<vfloat<N>>::storeu(valid,P+i, madd(1.0f-u,p0,u*p1));726if (dPdu ) mem<vfloat<N>>::storeu(valid,dPdu+i, p1-p0);727if (ddPdudu) mem<vfloat<N>>::storeu(valid,ddPdudu+i,vfloat<N>(zero));728}729}730731/* interpolation for vertex buffers */732else733{734assert(bufferSlot < numTimeSteps);735const char* vsrc = vertices[bufferSlot].getPtr();736const char* tsrc = tangents[bufferSlot].getPtr();737const size_t vstride = vertices[bufferSlot].getStride();738const size_t tstride = vertices[bufferSlot].getStride();739740for (unsigned int i=0; i<valueCount; i+=N)741{742const size_t ofs = i*sizeof(float);743const size_t index = curves[primID];744const vbool<N> valid = vint<N>((int)i)+vint<N>(step) < vint<N>((int)valueCount);745const vfloat<N> p0 = mem<vfloat<N>>::loadu(valid,(float*)&vsrc[(index+0)*vstride+ofs]);746const vfloat<N> p1 = mem<vfloat<N>>::loadu(valid,(float*)&vsrc[(index+1)*vstride+ofs]);747const vfloat<N> t0 = mem<vfloat<N>>::loadu(valid,(float*)&tsrc[(index+0)*tstride+ofs]);748const vfloat<N> t1 = mem<vfloat<N>>::loadu(valid,(float*)&tsrc[(index+1)*tstride+ofs]);749750const HermiteCurveT<vfloat<N>> curve(p0,t0,p1,t1);751if (P ) mem<vfloat<N>>::storeu(valid,P+i, curve.eval(u));752if (dPdu ) mem<vfloat<N>>::storeu(valid,dPdu+i, curve.eval_du(u));753if (ddPdudu) mem<vfloat<N>>::storeu(valid,ddPdudu+i,curve.eval_dudu(u));754}755}756}757758void interpolate(const RTCInterpolateArguments* const args) {759interpolate_impl<4>(args);760}761};762}763764DECLARE_ISA_FUNCTION(CurveGeometry*, createCurves, Device* COMMA Geometry::GType);765}766767768