-
Notifications
You must be signed in to change notification settings - Fork 0
/
tfxParser.ts
71 lines (57 loc) · 2.58 KB
/
tfxParser.ts
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
export interface TfxFileHeader {
// Specifies TressFX version number
version: number; // float version;
// Number of hair strands in this file. All strands in this file are guide strands.
// Follow hair strands are generated procedurally.
numHairStrands: number; // unsigned int numHairStrands;
// From 4 to 64 inclusive (POW2 only). This should be a fixed value within tfx value.
// The total vertices from the tfx file is numHairStrands * numVerticesPerStrand.
numVerticesPerStrand: number; // unsigned int numVerticesPerStrand;
// Offsets to array data starts here. Offset values are in bytes, aligned on 8 bytes boundaries,
// and relative to beginning of the .tfx file
// ALL ARE UNSIGNED INTS!
offsetVertexPosition: number; // Array size: FLOAT4[numHairStrands]
offsetStrandUV: number; // Array size: FLOAT2[numHairStrands], if 0 no texture coordinates
offsetVertexUV: number; // Array size: FLOAT2[numHairStrands * numVerticesPerStrand], if 0, no per vertex texture coordinates
offsetStrandThickness: number; // Array size: float[numHairStrands]
offsetVertexColor: number; // Array size: FLOAT4[numHairStrands * numVerticesPerStrand], if 0, no vertex colors
// unsigned int reserved[32]; // Reserved for future versions
}
export interface TfxFileData {
header: TfxFileHeader;
totalVertices: number;
vertexPositionsBuffer: Float32Array;
}
const requestBinaryFile = async (path: string) => {
const resp = await fetch(path);
if (!resp.ok) {
throw `Could not download tfx file '${path}'`;
}
return await resp.arrayBuffer();
};
const parseHeader = (rawData: ArrayBuffer): TfxFileHeader => {
const version = new Float32Array(rawData, 0, 1)[0]; // offset 0bytes, read single float
const uints = new Uint32Array(rawData, 4, 7); // offset 4bytes cause version is float, read 7 uint-values
return {
version,
numHairStrands: uints[0],
numVerticesPerStrand: uints[1],
offsetVertexPosition: uints[2],
offsetStrandUV: uints[3],
offsetVertexUV: uints[4],
offsetStrandThickness: uints[5],
offsetVertexColor: uints[6],
};
};
export const loadTfxFile = async (path: string): Promise<TfxFileData> => {
const fileData = await requestBinaryFile(path);
const header = parseHeader(fileData);
console.log('Loaded Tfx file with header', header);
const totalVertices = header.numHairStrands * header.numVerticesPerStrand;
const positionsBuf = new Float32Array(fileData, header.offsetVertexPosition, totalVertices * 4);
return {
header,
totalVertices,
vertexPositionsBuffer: positionsBuf,
};
};