2008年9月13日星期六

3DS轉換矩陣

經過半天的勞力,終於成功載入轉換矩陣 (0x4160 trunk),全靠 lib3ds 的原碼。

// Trunk 0x4160 comes before 0x4120,
// during the loading of 0x4160 we got the information to
// change the clockwise/anti-clockwise triangle winding or not
// and apply this information during the loading of 0x4120
bool invertTriangleWinding = false;

// ...

// Loading the local coordinates chunk
// It's base from lib3ds: http://www.lib3ds.org
case 0x4160:
{
// We are using row major matrix
Mat44f matrix = Mat44f::cIdentity;
for(size_t i=0; i<4; ++i)
mStream->read(matrix.row[i], sizeof(float) * 3);

// Flip X coordinate of vertices if mesh matrix has negative determinant
if((invertWinding = (matrix.determinant() < 0)) == true) {
Mat44f inv = matrix.inverse();

matrix.m00 = -matrix.m00;
matrix.m01 = -matrix.m01;
matrix.m02 = -matrix.m02;
matrix.m03 = -matrix.m03;

matrix = (inv * matrix).transpose();

size_t vertexCount = getVertexCount();
Vec3f* vertex = getVertexPointer();

for(size_t i=0; i<vertexCount; ++i) {
// Transform tmp using matrix, where matrix[3] holds the translation
#ifdef FLIP_YZ_AXIS
Vec4f tmp(vertex[i].x, -vertex[i].z, vertex[i].y, 0);
tmp = (matrix * tmp) + matrix[3];
vertex[i] = Vec3f(tmp.x, tmp.z, -tmp.y);
#else
Vec4f tmp(vertex[i].x, vertex[i].y, vertex[i].z, 0);
tmp = (matrix * tmp) + matrix[3];
vertex[i] = Vec3f(tmp.x, tmp.y, tmp.z);
#endif
}
}
} break;

// ...

// Loading the face description (index values) trunk
case 0x4120:
{
uint16_t faceCount = 0;
uint16_t* indexArray = nullptr;

// ...

if(invertTriangleWinding) {
for(size_t i=0; i<faceCount*3; i+=3)
std::swap(indexArray[i], indexArray[i+2]);
}
} break;

3 則留言:

  1. HI~你好,請問拿到3DS的矩陣後,要如何重新用來計算新的頂點?程式碼看不是很懂.沒套轉換矩陣讀出來的3DS做出的模型有些會身首分離,不知是不是這個原因..Orz

    回覆刪除
  2. 其實我也弄不清 3DS 裡頭的那個矩陣代表什麼,不過忽視它的話做出來的模型就多數會身首分離.如果你知道它的意義,敬請指教指教 :)

    回覆刪除
  3. 感謝回答~~~
    不知你可否試試http://humanfly.myweb.hinet.net/car.3DS 這個檔案是否可以正常顯示~目前我不管變換矩陣後,輪胎跟車燈等等會在外面,理他的話似乎公式也不對Orz

    回覆刪除