FaceGen 3 SDKs Reference
Loading...
Searching...
No Matches
FgApplyDna.cpp
1//
2// Copyright (c) Singular Inversions Inc. 2014
3//
4// Authors: Andrew Beatty
5// Created: Jan 2, 2014
6//
7
8#include "stdafx.h"
9
10#include "FgApply.hpp"
11#include "FgMain.hpp"
12#include "FgTestUtils.hpp"
13#include "FgBuild.hpp"
14#include "Fg3Face.hpp"
15#include "Fg3dMeshIo.hpp"
16#include "Fg3Sam.hpp"
17#include "Fg3Freeform.hpp"
18#include "FgParse.hpp"
19#include "FgApply.hpp"
20#include "Fg3dDisplay.hpp"
21
22using namespace std;
23
24namespace Fg {
25
26namespace {
27
28void endianFlip_(uint16 & v)
29{
30 uchar *ptr = reinterpret_cast<uchar*>(&v);
31 swap(ptr[0],ptr[1]);
32}
33void endianFlip_(uint32 & v)
34{
35 uchar *ptr = reinterpret_cast<uchar*>(&v);
36 swap(ptr[0],ptr[3]);
37 swap(ptr[1],ptr[2]);
38}
39void endianFlip_(float & v)
40{
41 uchar *ptr = reinterpret_cast<uchar*>(&v);
42 swap(ptr[0],ptr[3]);
43 swap(ptr[1],ptr[2]);
44}
45template<typename T>
46inline T endianFlip(T v) {endianFlip_(v); return v; }
47
48struct DnaSectionLookup
49{
50 uint32 descriptor;
51 uint32 definition;
52 uint32 behavior;
53 uint32 controls;
54 uint32 joints;
55 uint32 blendShapeChannels;
56 uint32 animateMaps;
57 uint32 geometry;
58};
59
60void checkSig_(Bytes const & blob,size_t & pos)
61{
62 Arr3UC sig = dsrlzT_<Arr3UC>(blob,pos);
63 if (sig != Arr3UC{'D','N','A'})
64 fgThrow("not a DNA file");
65 uint16 verMaj = endianFlip(dsrlzT_<uint16>(blob,pos)),
66 verMin = endianFlip(dsrlzT_<uint16>(blob,pos));
67 if (verMaj != 2)
68 fgThrow("unsupported DNA file major version",toStr(verMaj));
69 if (verMin != 1)
70 fgWarn("unsupported DNA file minor versino",toStr(verMin));
71}
72
73template<typename T>
74T get_(Bytes const & blob,size_t & pos) {return endianFlip(dsrlzT_<T>(blob,pos)); }
75
76template<typename T>
77Uints gets_(Bytes const & blob,size_t & pos)
78{
79 size_t sz = get_<uint32>(blob,pos);
80 Uints ret; ret.reserve(sz);
81 for (size_t ii=0; ii<sz; ++ii)
82 ret.push_back(get_<T>(blob,pos));
83 return ret;
84}
85
86DnaSectionLookup getDsl(Bytes const & blob,size_t & pos)
87{
88 auto get32 = [&](){return get_<uint32>(blob,pos); };
89 DnaSectionLookup dsl;
90 dsl.descriptor = get32();
91 dsl.definition = get32();
92 dsl.behavior = get32();
93 dsl.controls = get32();
94 dsl.joints = get32();
95 dsl.blendShapeChannels = get32();
96 dsl.animateMaps = get32();
97 dsl.geometry = get32();
98 return dsl;
99}
100
101Vec2Fs getVec2Fs_(Bytes const & blob,size_t & pos)
102{
103 uint32 sz = get_<uint32>(blob,pos); // number of X values
104 Vec2Fs vecs (sz);
105 for (size_t vv=0; vv<sz; ++vv)
106 vecs[vv][0] = get_<float>(blob,pos); // read X values
107 FGASSERT(get_<uint32>(blob,pos) == sz); // number of Y values
108 for (size_t vv=0; vv<sz; ++vv)
109 vecs[vv][1] = get_<float>(blob,pos); // read Y values
110 return vecs;
111};
112
113Vec3Fs getVec3Fs_(Bytes const & blob,size_t & pos) // as above
114{
115 auto get32 = [&](){return get_<uint32>(blob,pos); };
116 auto getFlt = [&](){return get_<float>(blob,pos); };
117 uint32 sz = get32();
118 Vec3Fs vecs (sz);
119 for (size_t vv=0; vv<sz; ++vv)
120 vecs[vv][0] = getFlt();
121 FGASSERT(get32() == sz);
122 for (size_t vv=0; vv<sz; ++vv)
123 vecs[vv][1] = getFlt();
124 FGASSERT(get32() == sz);
125 for (size_t vv=0; vv<sz; ++vv)
126 vecs[vv][2] = getFlt();
127 return vecs;
128};
129
130}
131
132// DNA format from ~MetaHuman-DNA-Calibration/dnacalib/DNACalib/src/dna/DNA.h
133Meshes dnaImport(Bytes const & blob)
134{
135 Meshes ret;
136 size_t pos {0};
137 checkSig_(blob,pos);
138 auto get16 = [&](){return get_<uint16>(blob,pos); };
139 auto get32 = [&](){return get_<uint32>(blob,pos); };
140 auto get16s = [&](){return gets_<uint16>(blob,pos); };
141 auto get32s = [&](){return gets_<uint32>(blob,pos); };
142 auto getVec2Fs = [&](){return getVec2Fs_(blob,pos); };
143 auto getVec3Fs = [&](){return getVec3Fs_(blob,pos); };
144 auto getVertInds = [&](Vec3UIs & tris,Vec4UIs & quads)
145 {
146 uint32 sz = get32();
147 for (size_t ii=0; ii<sz; ++ii) {
148 uint32 len = get32();
149 if (len == 3) {
150 Vec3UI v;
151 for (size_t jj=0; jj<3; ++jj)
152 v[jj] = get32();
153 tris.push_back(v);
154 }
155 else if (len == 4) {
156 Vec4UI v;
157 for (size_t jj=0; jj<4; ++jj)
158 v[jj] = get32();
159 quads.push_back(v);
160 }
161 else
162 fgThrow("unhandled polygon size",toStr(len));
163 }
164 };
165 auto getLodInds = [&]()
166 {
167 Uints lods = get16s();
168 size_t sz = get32();
169 Uintss ret (sz);
170 for (Uints & row : ret)
171 row = get16s();
172 return ret;
173 };
174 auto getStrings = [&]()
175 {
176 size_t sz = get32();
177 Strings ret (sz);
178 for (String & str : ret) {
179 size_t ss = get32();
180 FGASSERT(pos+ss <= blob.size());
181 str = String{reinterpret_cast<char const *>(&blob[pos]),ss};
182 pos += ss;
183 }
184 return ret;
185 };
186 DnaSectionLookup dsl = getDsl(blob,pos);
187 pos = dsl.definition;
188 // for each LOD, the list of indices into the given data list:
189 Uintss jointLodInds = getLodInds(),
190 blendLodInds = getLodInds(),
191 animLodInds = getLodInds(),
192 meshLodInds = getLodInds();
193 Strings guiControlNames = getStrings(),
194 rawControlNames = getStrings(),
195 jointNames = getStrings(),
196 blendShapeChannelNames = getStrings(),
197 animatedMapNames = getStrings(),
198 meshNames = getStrings();
199 pos = dsl.geometry; // skip ahead to geometry (also skips marker at beginning of geometry)
200 uint32 numMeshes = get32();
201 FGASSERT(numMeshes == meshNames.size());
202 for (size_t mm=0; mm<numMeshes; ++mm) {
203 uint32 offset = get32(); // offset to next mesh or record
204 Vec3Fs verts = getVec3Fs();
205 Vec2Fs uvs = getVec2Fs();
206 Vec3Fs norms = getVec3Fs();
207 Uints vertList = get32s(), // indices into 'verts'
208 uvList = get32s(), // indices into 'uvs'
209 normList = get32s(); // indices into 'norms'
210 size_t listSz = vertList.size();
211 FGASSERT(uvList.size() == listSz);
212 FGASSERT(normList.size() == listSz);
213 Vec3UIs triInds; // indices into 'vertList', 'uvList' and 'normList' for each tri
214 Vec4UIs quadInds; // indices into 'vertList', 'uvList' and 'normList' for each quad
215 getVertInds(triInds,quadInds);
216 /*ushort maxInfluence =*/ get16();
217
218 TriInds tInds; tInds.reserve(triInds.size());
219 for (Vec3UI tri : triInds) {
220 tInds.vertInds.emplace_back(vertList[tri[0]],vertList[tri[1]],vertList[tri[2]]);
221 tInds.uvInds.emplace_back(uvList[tri[0]],uvList[tri[1]],uvList[tri[2]]);
222 }
223 QuadInds qInds; qInds.reserve(quadInds.size());
224 for (Vec4UI q : quadInds) {
225 qInds.vertInds.emplace_back(vertList[q[0]],vertList[q[1]],vertList[q[2]],vertList[q[3]]);
226 qInds.uvInds.emplace_back(uvList[q[0]],uvList[q[1]],uvList[q[2]],uvList[q[3]]);
227 }
228 Strings names = splitChar(meshNames[mm],'_');
229 String name = names[1] + '-' + names[0];
230 ret.push_back(Mesh{name,verts,uvs,{Surf{tInds,qInds}}}); // emplace_back doesn't like optional args
231 pos = offset; // jump to next mesh
232 }
233 return ret;
234}
235
236void dnaInject_(Vec3Fss const & shapes,Bytes & blob)
237{
238 size_t pos {0};
239 checkSig_(blob,pos);
240 auto get32 = [&](){return get_<uint32>(blob,pos); };
241 DnaSectionLookup dsl = getDsl(blob,pos);
242 pos = dsl.geometry;
243 uint32 numMeshes = get32();
244 if (numMeshes != shapes.size())
245 fgThrow("number of vertex lists to inject differ from dna mesh count",toStr(shapes.size())+"!="+toStr(numMeshes));
246 for (size_t mm=0; mm<numMeshes; ++mm) {
247 Vec3Fs const & shape = shapes[mm];
248 uint32 offset = get32(); // offset to next mesh or record
249 for (uint jj=0; jj<3; ++jj) {
250 uint32 sz = get32();
251 if (sz != shape.size())
252 fgThrow("vertex count differs for mesh",toStr(mm));
253 for (size_t vv=0; vv<sz; ++vv) {
254 float v = shape[vv][jj];
255 byte *ptr = reinterpret_cast<byte*>(&v);
256 swap(ptr[0],ptr[3]);
257 swap(ptr[1],ptr[2]);
258 memcpy(&blob[pos],ptr,4);
259 pos += 4;
260 }
261 }
262 pos = offset; // move to next mesh
263 }
264}
265
266}