TriMesh::fromBlender improvements contributed by Francesc Juhé
parent
d02d4ebedf
commit
48730364a4
|
@ -864,6 +864,7 @@ void TriMesh::serialize(Stream *stream, InstanceManager *manager) const {
|
||||||
|
|
||||||
ref<TriMesh> TriMesh::fromBlender(const std::string &name,
|
ref<TriMesh> TriMesh::fromBlender(const std::string &name,
|
||||||
size_t faceCount, void *_facePtr, size_t vertexCount, void *_vertexPtr, void *_uvPtr, void *_colPtr, short mat_nr) {
|
size_t faceCount, void *_facePtr, size_t vertexCount, void *_vertexPtr, void *_uvPtr, void *_colPtr, short mat_nr) {
|
||||||
|
const int ME_SMOOTH = 1;
|
||||||
struct MFace {
|
struct MFace {
|
||||||
uint32_t v[4];
|
uint32_t v[4];
|
||||||
int16_t mat_nr;
|
int16_t mat_nr;
|
||||||
|
@ -880,32 +881,46 @@ ref<TriMesh> TriMesh::fromBlender(const std::string &name,
|
||||||
uint8_t a, r, g, b;
|
uint8_t a, r, g, b;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct MLoopUV {
|
struct MTFace {
|
||||||
float uv[2];
|
float uv[4][2];
|
||||||
int32_t flag;
|
void *tpage;
|
||||||
|
uint8_t flag, transp;
|
||||||
|
uint16_t mode, tile, unwrap;
|
||||||
};
|
};
|
||||||
|
|
||||||
MFace *facePtr = (MFace *) _facePtr;
|
MFace *facePtr = (MFace *) _facePtr;
|
||||||
MVert *vertexPtr = (MVert *) _vertexPtr;
|
MVert *vertexPtr = (MVert *) _vertexPtr;
|
||||||
MCol *colPtr = (MCol *) _colPtr;
|
MCol *colPtr = (MCol *) _colPtr;
|
||||||
MLoopUV *uvPtr = (MLoopUV *) _uvPtr;
|
MTFace *uvPtr = (MTFace *) _uvPtr;
|
||||||
|
|
||||||
boost::unordered_map<uint32_t, uint32_t> vertexMap;
|
boost::unordered_map<uint64_t, uint32_t> vertexMap;
|
||||||
|
boost::unordered_map<uint64_t, uint8_t> vertexFaceMap;
|
||||||
uint32_t triangleCtr = 0, vertexCtr = 0;
|
uint32_t triangleCtr = 0, vertexCtr = 0;
|
||||||
|
|
||||||
for (uint32_t i=0; i<faceCount; ++i) {
|
for (uint32_t faceID=0; faceID<faceCount; ++faceID) {
|
||||||
const MFace &face = facePtr[i];
|
const MFace &face = facePtr[faceID];
|
||||||
|
|
||||||
if (face.mat_nr == mat_nr) {
|
if (face.mat_nr == mat_nr) {
|
||||||
|
uint64_t base = ((face.flag & ME_SMOOTH) && (uvPtr == NULL) && (colPtr == NULL)) ? 0ULL : ((uint64_t) (faceID + 1) << 32ULL);
|
||||||
bool triangle = face.v[3] == 0;
|
bool triangle = face.v[3] == 0;
|
||||||
for (int j=0; j<(triangle ? 3 : 4); ++j) {
|
int nVertices = triangle ? 3 : 4;
|
||||||
if (vertexMap.find(face.v[j]) == vertexMap.end())
|
|
||||||
vertexMap[face.v[j]] = vertexCtr++;
|
for (int j=0; j<nVertices; ++j) {
|
||||||
|
uint64_t key = face.v[j] + base;
|
||||||
|
if (vertexMap.find(key) == vertexMap.end()) {
|
||||||
|
vertexMap[key] = vertexCtr++;
|
||||||
|
vertexFaceMap[key] = (uint8_t) j;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
triangleCtr += triangle ? 1 : 2;
|
triangleCtr += triangle ? 1 : 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (triangleCtr == 0) {
|
||||||
|
/* There were no faces with this material -- return NULL */
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
ref<TriMesh> triMesh = new TriMesh(name, triangleCtr, vertexCtr, true,
|
ref<TriMesh> triMesh = new TriMesh(name, triangleCtr, vertexCtr, true,
|
||||||
uvPtr != NULL, colPtr != NULL);
|
uvPtr != NULL, colPtr != NULL);
|
||||||
|
|
||||||
|
@ -915,49 +930,79 @@ ref<TriMesh> TriMesh::fromBlender(const std::string &name,
|
||||||
Color3 *vertexColors = (Color3 *) triMesh->getVertexColors();
|
Color3 *vertexColors = (Color3 *) triMesh->getVertexColors();
|
||||||
Point2 *vertexTexcoords = (Point2 *) triMesh->getVertexTexcoords();
|
Point2 *vertexTexcoords = (Point2 *) triMesh->getVertexTexcoords();
|
||||||
|
|
||||||
for (uint32_t i=0; i<faceCount; ++i) {
|
for (uint32_t faceID=0; faceID<faceCount; ++faceID) {
|
||||||
const MFace &face = facePtr[i];
|
const MFace &face = facePtr[faceID];
|
||||||
|
|
||||||
if (face.mat_nr == mat_nr) {
|
if (face.mat_nr == mat_nr) {
|
||||||
*triangles++ = vertexMap[face.v[0]];
|
uint64_t base = ((face.flag & ME_SMOOTH) && (uvPtr == NULL) && (colPtr == NULL)) ? 0ULL : ((uint64_t) (faceID + 1) << 32ULL);
|
||||||
*triangles++ = vertexMap[face.v[1]];
|
bool triangle = face.v[3] == 0;
|
||||||
*triangles++ = vertexMap[face.v[2]];
|
|
||||||
|
|
||||||
if (face.v[3] != 0) {
|
*triangles++ = vertexMap[base + face.v[0]];
|
||||||
*triangles++ = vertexMap[face.v[0]];
|
*triangles++ = vertexMap[base + face.v[1]];
|
||||||
*triangles++ = vertexMap[face.v[2]];
|
*triangles++ = vertexMap[base + face.v[2]];
|
||||||
*triangles++ = vertexMap[face.v[3]];
|
|
||||||
|
if (!triangle) {
|
||||||
|
*triangles++ = vertexMap[base + face.v[0]];
|
||||||
|
*triangles++ = vertexMap[base + face.v[2]];
|
||||||
|
*triangles++ = vertexMap[base + face.v[3]];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((face.flag & ME_SMOOTH) == 0) {
|
||||||
|
Point p0(vertexPtr[face.v[0]].co[0], vertexPtr[face.v[0]].co[1], vertexPtr[face.v[0]].co[2]);
|
||||||
|
Point p1(vertexPtr[face.v[1]].co[0], vertexPtr[face.v[1]].co[1], vertexPtr[face.v[1]].co[2]);
|
||||||
|
Point p2(vertexPtr[face.v[2]].co[0], vertexPtr[face.v[2]].co[1], vertexPtr[face.v[2]].co[2]);
|
||||||
|
Vector side1(p1-p0), side2(p2-p0);
|
||||||
|
Normal faceNormal(cross(side1, side2));
|
||||||
|
Float length = faceNormal.length();
|
||||||
|
if (!faceNormal.isZero())
|
||||||
|
faceNormal /= length;
|
||||||
|
|
||||||
|
int nVertices = triangle ? 3 : 4;
|
||||||
|
for (int i=0; i<nVertices; ++i)
|
||||||
|
vertexNormals[vertexMap[base + face.v[i]]] = faceNormal;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const float normalScale = 1.0f / 32767.0f;
|
const float normalScale = 1.0f / 32767.0f;
|
||||||
const float rgbScale = 1.0f / 255.0f;
|
const float rgbScale = 1.0f / 255.0f;
|
||||||
|
const uint64_t vertexMask = 0x00000000FFFFFFFFULL;
|
||||||
|
const uint64_t faceMask = 0xFFFFFFFF00000000ULL;
|
||||||
|
|
||||||
for (boost::unordered_map<uint32_t, uint32_t>::iterator it = vertexMap.begin();
|
for (boost::unordered_map<uint64_t, uint32_t>::iterator it = vertexMap.begin();
|
||||||
it != vertexMap.end(); ++it) {
|
it != vertexMap.end(); ++it) {
|
||||||
const MVert &vertex = vertexPtr[it->first];
|
const MVert &vertex = vertexPtr[it->first & vertexMask];
|
||||||
|
bool isSmooth = (it->first & faceMask) == 0;
|
||||||
uint32_t idx = it->second;
|
uint32_t idx = it->second;
|
||||||
|
|
||||||
vertexPositions[idx] = Point3(vertex.co[0], vertex.co[1], vertex.co[2]);
|
vertexPositions[idx] = Point(vertex.co[0], vertex.co[1], vertex.co[2]);
|
||||||
vertexNormals[idx] = normalize(Normal(
|
|
||||||
vertex.no[0] * normalScale,
|
|
||||||
vertex.no[1] * normalScale,
|
|
||||||
vertex.no[2] * normalScale
|
|
||||||
));
|
|
||||||
|
|
||||||
if (uvPtr) {
|
if ((it->first & faceMask) != 0) {
|
||||||
const MLoopUV &uv = uvPtr[it->first];
|
uint32_t faceID = (uint32_t)((it->first >> 32ULL) & 0xFFFFFFFFULL) - 1;
|
||||||
vertexTexcoords[idx] = Point2(uv.uv[0], uv.uv[1]);
|
const MFace &face = facePtr[faceID];
|
||||||
|
isSmooth = (face.flag & ME_SMOOTH) != 0;
|
||||||
|
|
||||||
|
if (uvPtr) {
|
||||||
|
const MTFace &uv = uvPtr[faceID];
|
||||||
|
vertexTexcoords[idx] = Point2(uv.uv[vertexFaceMap[it->first]][0], 1 - uv.uv[vertexFaceMap[it->first]][1]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (colPtr) {
|
||||||
|
const MCol &col = colPtr[(uint32_t) ( faceID * 4 ) + (uint32_t) vertexFaceMap[it->first]];
|
||||||
|
vertexColors[idx] = Color3(
|
||||||
|
col.b * rgbScale,
|
||||||
|
col.g * rgbScale,
|
||||||
|
col.r * rgbScale
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (colPtr) {
|
if (isSmooth) {
|
||||||
const MCol &col = colPtr[it->first];
|
vertexNormals[idx] = normalize(Normal(
|
||||||
vertexColors[idx] = Color3(
|
vertex.no[0] * normalScale,
|
||||||
col.r * rgbScale,
|
vertex.no[1] * normalScale,
|
||||||
col.g * rgbScale,
|
vertex.no[2] * normalScale
|
||||||
col.b * rgbScale
|
));
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue