#include "shared/hash-functions.hlsl" #include "shared/noise-functions.hlsl" #include "shared/point.hlsl" #include "shared/quat-functions.hlsl" #include "shared/pbr.hlsl" cbuffer Params : register(b0) { } StructuredBuffer Points : t0; // input StructuredBuffer Vertices: t1; StructuredBuffer Indices: t2; RWStructuredBuffer ResultPoints : u0; // output float dot2( in float3 v ) { return dot(v,v); } float udTriangle( in float3 v1, in float3 v2, in float3 v3, in float3 p ) { // prepare data float3 v21 = v2 - v1; float3 p1 = p - v1; float3 v32 = v3 - v2; float3 p2 = p - v2; float3 v13 = v1 - v3; float3 p3 = p - v3; float3 nor = cross( v21, v13 ); return sqrt( // inside/outside test (sign(dot(cross(v21,nor),p1)) + sign(dot(cross(v32,nor),p2)) + sign(dot(cross(v13,nor),p3))<2.0) ? // 3 edges min( min( dot2(v21*clamp(dot(v21,p1)/dot2(v21),0.0,1.0)-p1), dot2(v32*clamp(dot(v32,p2)/dot2(v32),0.0,1.0)-p2) ), dot2(v13*clamp(dot(v13,p3)/dot2(v13),0.0,1.0)-p3) ) : // 1 face dot(nor,p1)*dot(nor,p1)/dot2(nor) ); } float3 closestPointOnTriangle( in float3 p0, in float3 p1, in float3 p2, in float3 sourcePosition ) { float3 edge0 = p1 - p0; float3 edge1 = p2 - p0; float3 v0 = p0 - sourcePosition; // float a = edge0.dot( edge0 ); // float b = edge0.dot( edge1 ); // float c = edge1.dot( edge1 ); // float d = edge0.dot( v0 ); // float e = edge1.dot( v0 ); float a = dot(edge0, edge0 ); float b = dot(edge0, edge1 ); float c = dot(edge1, edge1 ); float d = dot(edge0, v0 ); float e = dot(edge1, v0 ); float det = a*c - b*b; float s = b*e - c*d; float t = b*d - a*e; if ( s + t < det ) { if ( s < 0.f ) { if ( t < 0.f ) { if ( d < 0.f ) { s = clamp( -d/a, 0.f, 1.f ); t = 0.f; } else { s = 0.f; t = clamp( -e/c, 0.f, 1.f ); } } else { s = 0.f; t = clamp( -e/c, 0.f, 1.f ); } } else if ( t < 0.f ) { s = clamp( -d/a, 0.f, 1.f ); t = 0.f; } else { float invDet = 1.f / det; s *= invDet; t *= invDet; } } else { if ( s < 0.f ) { float tmp0 = b+d; float tmp1 = c+e; if ( tmp1 > tmp0 ) { float numer = tmp1 - tmp0; float denom = a-2*b+c; s = clamp( numer/denom, 0.f, 1.f ); t = 1-s; } else { t = clamp( -e/c, 0.f, 1.f ); s = 0.f; } } else if ( t < 0.f ) { if ( a+d > b+e ) { float numer = c+e-b-d; float denom = a-2*b+c; s = clamp( numer/denom, 0.f, 1.f ); t = 1-s; } else { s = clamp( -e/c, 0.f, 1.f ); t = 0.f; } } else { float numer = c+e-b-d; float denom = a-2*b+c; s = clamp( numer/denom, 0.f, 1.f ); t = 1.f - s; } } return p0 + s * edge0 + t * edge1; } [numthreads(64,1,1)] void main(uint3 i : SV_DispatchThreadID) { uint pointCount, pointStride; Points.GetDimensions(pointCount, pointStride); if(i.x >= pointCount) { ResultPoints[i.x].W = 0 ; return; } uint vertexCount, vertexStride; Vertices.GetDimensions(vertexCount, vertexStride); uint faceCount, faceStride; Indices.GetDimensions(faceCount, faceStride); LegacyPoint p = Points[i.x]; int closestIndex = -1; float closestDistance = 99999; float3 pos = p.Position; float3 closestPoint; for(uint faceIndex = 0; faceIndex < faceCount; faceIndex++) { int3 f = Indices[faceIndex]; float3 pointOnFace = closestPointOnTriangle( Vertices[f[0]].Position, Vertices[f[1]].Position, Vertices[f[2]].Position, pos ); float distance2 = length(pointOnFace - pos); if(distance2 < closestDistance) { closestDistance = distance2; closestIndex = faceIndex; closestPoint = pointOnFace; } } if(closestIndex>=0) { p.Position = closestPoint; } ResultPoints[i.x] = p; }