110 qInfo(
"\tcomputing normals\n");
112 MatrixX3f r1(
tris.rows(), 3);
113 MatrixX3f r2(
tris.rows(), 3);
114 MatrixX3f r3(
tris.rows(), 3);
116 for (qint32 i = 0; i <
tris.rows(); ++i) {
117 r1.row(i) =
rr.row(
tris(i, 0));
118 r2.row(i) =
rr.row(
tris(i, 1));
119 r3.row(i) =
rr.row(
tris(i, 2));
122 MatrixX3f x = r2 - r1;
123 MatrixX3f y = r3 - r1;
124 MatrixX3f tri_nn(x.rows(), y.cols());
125 tri_nn.col(0) = x.col(1).cwiseProduct(y.col(2)) - x.col(2).cwiseProduct(y.col(1));
126 tri_nn.col(1) = x.col(2).cwiseProduct(y.col(0)) - x.col(0).cwiseProduct(y.col(2));
127 tri_nn.col(2) = x.col(0).cwiseProduct(y.col(1)) - x.col(1).cwiseProduct(y.col(0));
130 MatrixX3f tmp = tri_nn.cwiseProduct(tri_nn);
131 VectorXf normSize = tmp.rowwise().sum();
132 normSize = normSize.cwiseSqrt();
134 for (qint32 i = 0; i < normSize.size(); ++i)
135 if (normSize(i) != 0)
136 tri_nn.row(i) /= normSize(i);
138 MatrixX3f
nn = MatrixX3f::Zero(
rr.rows(), 3);
140 for (qint32 p = 0; p <
tris.rows(); ++p) {
141 Vector3i verts =
tris.row(p);
142 for (qint32 j = 0; j < verts.size(); ++j)
143 nn.row(verts(j)) += tri_nn.row(p);
146 tmp =
nn.cwiseProduct(
nn);
147 normSize = tmp.rowwise().sum();
148 normSize = normSize.cwiseSqrt();
150 for (qint32 i = 0; i < normSize.size(); ++i)
151 if (normSize(i) != 0)
152 nn.row(i) /= normSize(i);
187 QFile t_File(p_sFile);
189 if (!t_File.open(QIODevice::ReadOnly)) {
190 qWarning(
"\tError: Couldn't open the surface file");
194 qInfo(
"Reading surface...\n");
197 qint32 t_NameIdx = 0;
198 if (p_sFile.contains(
"lh."))
199 t_NameIdx = p_sFile.indexOf(
"lh.");
200 else if (p_sFile.contains(
"rh."))
201 t_NameIdx = p_sFile.indexOf(
"rh.");
205 p_Surface.m_sFilePath = p_sFile.mid(0, t_NameIdx);
206 p_Surface.m_sFileName = p_sFile.mid(t_NameIdx, p_sFile.size() - t_NameIdx);
208 QDataStream t_DataStream(&t_File);
209 t_DataStream.setByteOrder(QDataStream::BigEndian);
233 if (nvert <= 0 || qint64(nvert) * (magic ==
QUAD_FILE_MAGIC_NUMBER ? 6 : 12) + qint64(nquad) * 12 > t_File.bytesAvailable()) {
234 qWarning(
"Invalid or truncated surface file %s", p_sFile.toUtf8().constData());
238 qInfo(
"\t%s is a quad file (nvert = %d nquad = %d)\n", p_sFile.toUtf8().constData(), nvert, nquad);
240 qInfo(
"\t%s is a new quad file (nvert = %d nquad = %d)\n", p_sFile.toUtf8().constData(), nvert, nquad);
243 verts.resize(3, nvert);
246 for (qint32 i = 0; i < nvert; ++i) {
247 for (qint32 j = 0; j < 3; ++j) {
248 t_DataStream >> iVal;
249 verts(j, i) =
static_cast<float>(iVal) / 100;
253 t_DataStream.readRawData(
reinterpret_cast<char*
>(verts.data()), nvert * 3 *
sizeof(
float));
254 for (qint32 i = 0; i < nvert; ++i)
255 for (qint32 j = 0; j < 3; ++j)
260 MatrixXi quads_new(4, nquad);
262 for (qint32 j = 0; j < quads.cols(); ++j) {
263 for (qint32 i = 0; i < quads.rows(); ++i) {
264 quads_new(i, j) = quads(count, 0);
268 quads = quads_new.transpose();
272 faces = MatrixXi::Zero(2 * nquad, 3);
273 for (qint32 k = 0; k < nquad; ++k) {
274 RowVectorXi quad = quads.row(k);
275 if ((quad[0] % 2) == 0) {
276 faces(nface, 0) = quad[0];
277 faces(nface, 1) = quad[1];
278 faces(nface, 2) = quad[3];
281 faces(nface, 0) = quad[2];
282 faces(nface, 1) = quad[3];
283 faces(nface, 2) = quad[1];
286 faces(nface, 0) = quad(0);
287 faces(nface, 1) = quad(1);
288 faces(nface, 2) = quad(2);
291 faces(nface, 0) = quad(0);
292 faces(nface, 1) = quad(2);
293 faces(nface, 2) = quad(3);
298 QString s = t_File.readLine();
301 t_DataStream >> nvert;
302 t_DataStream >> nface;
304 if (nvert <= 0 || nface < 0 || (qint64(nvert) + nface) * 12 > t_File.bytesAvailable()) {
305 qWarning(
"Invalid or truncated surface file %s", p_sFile.toUtf8().constData());
308 qInfo(
"\t%s is a triangle file (nvert = %d ntri = %d)\n", p_sFile.toUtf8().constData(), nvert, nface);
309 qInfo(
"\t%s", s.toUtf8().constData());
312 verts.resize(3, nvert);
313 t_DataStream.readRawData(
reinterpret_cast<char*
>(verts.data()), nvert * 3 *
sizeof(
float));
314 for (qint32 i = 0; i < 3; ++i)
315 for (qint32 j = 0; j < nvert; ++j)
319 faces.resize(nface, 3);
321 for (qint32 i = 0; i < nface; ++i) {
322 for (qint32 j = 0; j < 3; ++j) {
323 t_DataStream >> iVal;
328 qWarning(
"Bad magic number (%d) in surface file %s", magic, p_sFile.toUtf8().constData());
331 if (faces.size() > 0 && (faces.minCoeff() < 0 || faces.maxCoeff() >= nvert)) {
332 qWarning(
"Invalid or truncated surface file %s", p_sFile.toUtf8().constData());
336 verts.transposeInPlace();
337 verts.array() *= 0.001f;
339 p_Surface.m_matRR = verts.block(0, 0, verts.rows(), 3);
340 p_Surface.m_matTris = faces.block(0, 0, faces.rows(), 3);
343 p_Surface.m_matNN =
compute_normals(p_Surface.m_matRR, p_Surface.m_matTris);
346 if (t_File.fileName().contains(
"lh."))
347 p_Surface.m_iHemi = 0;
348 else if (t_File.fileName().contains(
"rh."))
349 p_Surface.m_iHemi = 1;
351 p_Surface.m_iHemi = -1;
356 p_Surface.m_sSurf = t_File.fileName().mid((t_NameIdx + 3), t_File.fileName().size() - (t_NameIdx + 3));
359 if (p_bLoadCurvature) {
360 QString t_sCurvatureFile = QString(
"%1%2.curv").arg(p_Surface.m_sFilePath).arg(p_Surface.m_iHemi == 0 ?
"lh" :
"rh");
366 qInfo(
"\tRead a surface with %d vertices from %s\n[done]\n", nvert, p_sFile.toUtf8().constData());