1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191
|
// Copyright 2009-2021 Intel Corporation
// SPDX-License-Identifier: Apache-2.0
#pragma once
#include "catmullclark_patch.h"
#include "bezier_curve.h"
namespace embree
{
template<typename Vertex, typename Vertex_t = Vertex>
class __aligned(64) BilinearPatchT
{
typedef CatmullClark1RingT<Vertex,Vertex_t> CatmullClarkRing;
typedef CatmullClarkPatchT<Vertex,Vertex_t> CatmullClarkPatch;
public:
Vertex v[4];
public:
__forceinline BilinearPatchT () {}
__forceinline BilinearPatchT (const HalfEdge* edge, const BufferView<Vertex>& vertices) {
init(edge,vertices.getPtr(),vertices.getStride());
}
__forceinline BilinearPatchT (const HalfEdge* edge, const char* vertices, size_t stride) {
init(edge,vertices,stride);
}
__forceinline void init (const HalfEdge* edge, const char* vertices, size_t stride)
{
v[0] = Vertex::loadu(vertices+edge->getStartVertexIndex()*stride); edge = edge->next();
v[1] = Vertex::loadu(vertices+edge->getStartVertexIndex()*stride); edge = edge->next();
v[2] = Vertex::loadu(vertices+edge->getStartVertexIndex()*stride); edge = edge->next();
v[3] = Vertex::loadu(vertices+edge->getStartVertexIndex()*stride); edge = edge->next();
}
__forceinline BilinearPatchT (const CatmullClarkPatch& patch)
{
v[0] = patch.ring[0].getLimitVertex();
v[1] = patch.ring[1].getLimitVertex();
v[2] = patch.ring[2].getLimitVertex();
v[3] = patch.ring[3].getLimitVertex();
}
__forceinline BBox<Vertex> bounds() const
{
BBox<Vertex> bounds (v[0]);
bounds.extend(v[1]);
bounds.extend(v[2]);
bounds.extend(v[3]);
return bounds;
}
__forceinline Vertex eval(const float uu, const float vv) const {
return lerp(lerp(v[0],v[1],uu),lerp(v[3],v[2],uu),vv);
}
__forceinline Vertex eval_du(const float uu, const float vv) const {
return lerp(v[1]-v[0],v[2]-v[3],vv);
}
__forceinline Vertex eval_dv(const float uu, const float vv) const {
return lerp(v[3]-v[0],v[2]-v[1],uu);
}
__forceinline Vertex eval_dudu(const float uu, const float vv) const {
return Vertex(zero);
}
__forceinline Vertex eval_dvdv(const float uu, const float vv) const {
return Vertex(zero);
}
__forceinline Vertex eval_dudv(const float uu, const float vv) const {
return (v[2]-v[3]) - (v[1]-v[0]);
}
__forceinline Vertex normal(const float uu, const float vv) const {
return cross(eval_du(uu,vv),eval_dv(uu,vv));
}
__forceinline void eval(const float u, const float v,
Vertex* P, Vertex* dPdu, Vertex* dPdv, Vertex* ddPdudu, Vertex* ddPdvdv, Vertex* ddPdudv,
const float dscale = 1.0f) const
{
if (P) {
*P = eval(u,v);
}
if (dPdu) {
assert(dPdu); *dPdu = eval_du(u,v)*dscale;
assert(dPdv); *dPdv = eval_dv(u,v)*dscale;
}
if (ddPdudu) {
assert(ddPdudu); *ddPdudu = eval_dudu(u,v)*sqr(dscale);
assert(ddPdvdv); *ddPdvdv = eval_dvdv(u,v)*sqr(dscale);
assert(ddPdudv); *ddPdudv = eval_dudv(u,v)*sqr(dscale);
}
}
template<class vfloat>
__forceinline Vec3<vfloat> eval(const vfloat& uu, const vfloat& vv) const
{
const vfloat x = lerp(lerp(v[0].x,v[1].x,uu),lerp(v[3].x,v[2].x,uu),vv);
const vfloat y = lerp(lerp(v[0].y,v[1].y,uu),lerp(v[3].y,v[2].y,uu),vv);
const vfloat z = lerp(lerp(v[0].z,v[1].z,uu),lerp(v[3].z,v[2].z,uu),vv);
return Vec3<vfloat>(x,y,z);
}
template<class vfloat>
__forceinline Vec3<vfloat> eval_du(const vfloat& uu, const vfloat& vv) const
{
const vfloat x = lerp(v[1].x-v[0].x,v[2].x-v[3].x,vv);
const vfloat y = lerp(v[1].y-v[0].y,v[2].y-v[3].y,vv);
const vfloat z = lerp(v[1].z-v[0].z,v[2].z-v[3].z,vv);
return Vec3<vfloat>(x,y,z);
}
template<class vfloat>
__forceinline Vec3<vfloat> eval_dv(const vfloat& uu, const vfloat& vv) const
{
const vfloat x = lerp(v[3].x-v[0].x,v[2].x-v[1].x,uu);
const vfloat y = lerp(v[3].y-v[0].y,v[2].y-v[1].y,uu);
const vfloat z = lerp(v[3].z-v[0].z,v[2].z-v[1].z,uu);
return Vec3<vfloat>(x,y,z);
}
template<typename vfloat>
__forceinline Vec3<vfloat> normal(const vfloat& uu, const vfloat& vv) const {
return cross(eval_du(uu,vv),eval_dv(uu,vv));
}
template<class vfloat>
__forceinline vfloat eval(const size_t i, const vfloat& uu, const vfloat& vv) const {
return lerp(lerp(v[0][i],v[1][i],uu),lerp(v[3][i],v[2][i],uu),vv);
}
template<class vfloat>
__forceinline vfloat eval_du(const size_t i, const vfloat& uu, const vfloat& vv) const {
return lerp(v[1][i]-v[0][i],v[2][i]-v[3][i],vv);
}
template<class vfloat>
__forceinline vfloat eval_dv(const size_t i, const vfloat& uu, const vfloat& vv) const {
return lerp(v[3][i]-v[0][i],v[2][i]-v[1][i],uu);
}
template<class vfloat>
__forceinline vfloat eval_dudu(const size_t i, const vfloat& uu, const vfloat& vv) const {
return vfloat(zero);
}
template<class vfloat>
__forceinline vfloat eval_dvdv(const size_t i, const vfloat& uu, const vfloat& vv) const {
return vfloat(zero);
}
template<class vfloat>
__forceinline vfloat eval_dudv(const size_t i, const vfloat& uu, const vfloat& vv) const {
return (v[2][i]-v[3][i]) - (v[1][i]-v[0][i]);
}
template<typename vbool, typename vfloat>
__forceinline void eval(const vbool& valid, const vfloat& uu, const vfloat& vv,
float* P, float* dPdu, float* dPdv, float* ddPdudu, float* ddPdvdv, float* ddPdudv,
const float dscale, const size_t dstride, const size_t N) const
{
if (P) {
for (size_t i=0; i<N; i++) vfloat::store(valid,P+i*dstride,eval(i,uu,vv));
}
if (dPdu) {
for (size_t i=0; i<N; i++) {
assert(dPdu); vfloat::store(valid,dPdu+i*dstride,eval_du(i,uu,vv)*dscale);
assert(dPdv); vfloat::store(valid,dPdv+i*dstride,eval_dv(i,uu,vv)*dscale);
}
}
if (ddPdudu) {
for (size_t i=0; i<N; i++) {
assert(ddPdudu); vfloat::store(valid,ddPdudu+i*dstride,eval_dudu(i,uu,vv)*sqr(dscale));
assert(ddPdvdv); vfloat::store(valid,ddPdvdv+i*dstride,eval_dvdv(i,uu,vv)*sqr(dscale));
assert(ddPdudv); vfloat::store(valid,ddPdudv+i*dstride,eval_dudv(i,uu,vv)*sqr(dscale));
}
}
}
};
typedef BilinearPatchT<Vec3fa,Vec3fa_t> BilinearPatch3fa;
}
|