void sampleTexture(...) {
// source texture (let's assume it is also quadratic)
const uint8_t* srcTexBuf = ...
size_t srcTexBufSize = ...
uint32_t srcTexWidth = ...
uint32_t srcTexHeight = ...
uint8_t srcBPP = ... // bytes per pixel
// source triangle in uv space
Vector2d A = ..., B = ..., C = ... // eg. 0/0, 1/1, 0/1
// determine optimal face resolution (power-of-two)
uint32_t potRes = ...
int8_t logDim = log2(potRes);
// allocate the target buffer for ptex
const size_t ptexBufSize = potRes*potRes*bpp;
uint8_t* ptexBuf = ...
// helper function (see below) to recursively generate potRes^2 uniformly subdivided triangle middle points
// (= the sampling points for the ptex texels)
std::vector<Vector2d> samplePoints;
generateSamplePoints(logDim, 0, A, B, C, samplePoints);
// sample the source texture and copy the texels into the ptex buffer
for (Vector2d p : samplePoints) {
// wrap UVs into to 0..1
if (p.x > 1.0 || p.x < 0.0) p.x -= std::floor(p.x);
if (p.y > 1.0 || p.y < 0.0) p.y -= std::floor(p.y);
// lookup source pixel
Vector2d uvt(p.x * srcTexWidth, p.y * srcTexHeight);
Vector2<uint32_t> uvi(std::floor(uvt.x), std::floor(uvt.y));
size_t srcTexIdx = bpp * (uvi.y*texWidth + uvi.x);
const uint8_t* srcTexData = &srcTexBuf[srcTexIdx];
// compute triangular texture index
Vector2d ptexUVT(p.x * potRes, p.y * potRes);
Vector2<uint32_t> ptexUVI(std::floor(ptexUVT.x), std::floor(ptexUVT.y));
Vector2d ptexDUV(ptexUVT.x - ptexUVI.x, ptexUVT.y - ptexUVI.y);
size_t ptxIdx = 0;
if (ptexDUV.x + ptexDUV.y <= 1.0) {
ptxIdx = ptexUVI.x + ptexUVI.y*potRes;
}
else {
ptxIdx = (potRes*potRes-1) - (ptexUVI.y+ptexUVI.x*potRes);
}
ptxIdx *= bpp;
// copy pixel
std::memcpy(&ptexBuf[ptxIdx], srcTexData, bpp);
}
// ... ptex writeFace ...
}
void generateSamplePoints(uint8_t N, uint8_t n, Vector2d T1, Vector2d T2, Vector2d T3, std::vector<Vector2d>& s) {
if (n == N) {
s.push_back(Vector2d((T1+T2+T3)/3.0);
return;
}
util::Vector2d A = 0.5 * (T1 + T2);
util::Vector2d B = 0.5 * (T2 + T3);
util::Vector2d C = 0.5 * (T1 + T3);
generateSamplePoints(N, n+1, T1, A, C, s);
generateSamplePoints(N, n+1, A, T2, B, s);
generateSamplePoints(N, n+1, B, T3, C, s);
generateSamplePoints(N, n+1, A, B, C, s);
}