| ŸƲ | 3ds max ī Direct3D ī ȯϱ |
| 4.0 | |
| Ű | GFX D3D DirectX Direct3D camera |
3ds max ī Direct3D ī ȯϷ ؾ ϴ°?
ϴ ַ п ʼ ⺻ ƴ϶, 3ds max ü ī ȯ(transform) Direct3D ī εǴ Ͽ ̴.
, 3ds max ī ϱ ͵ ϴ 캸. Ž ĺ̽(Sparks Knowledgebase) MaxSDK ̴ ( http://sparks.discreet.com. "max SDK docs" ϰ, "Index" Ʒ "Class GraphicsWindow" )
Class GraphicsWindow
Լ:
virtual void getCameraMatrix(float mat[4][4], Matrix3 *invTM, int *persp, float *hither, float *yon) = 0;:
ī Ӽ ´.:
float mat[4][4](projection, ) ϱ ȯ.Matrix3 *invTM̰ ī ȯ (affine) Ʈ (inverse)̴( Ʈ ƴ).int *persp(zero) ƴ (perspective) (view) ǹѴ; 0 (orthogonal).float *hitherٰŸ Ŭ(Near clip) .float *yonŸ Ŭ(Far clip) .
3ds max ϴ ü ҽ ڵ ƴ, ܰ躰 ߱ ϱ ̴.
ΰ ǵ:
D3DXMATRIX m_d3dWorldXform; // ø̼ ȯ D3DXMATRIX m_d3dViewXform; // ø̼ ȯ D3DXMATRIX m_d3dProjXform; // ø̼ ȯ Interface *ip = GetCOREInterface(); // 3ds max ̽(glabol access interface) Ѵ. ViewExp * pView = ip->GetActiveViewport(); // ȰȭǾ ִ Ʈ Ѵ. GraphicsWindow *gw = pView->getGW(); // GraphicsWindow ؽƮ ´. getCameraMatrix( mat, invTM, persp, hither, yon); // ̷ ´. ŸԿ ؼ . float oneOverDepth = 1.0f / (yon - hither);
ƽ ͷκ Direct3D ī ϱ Ͽ 츮 ̴.
// Direct3D ī (Camera View Position) ī (Camera // Projection) ȯ(Transforms) Ѵ. // // ù° ǥ NPC ȯϴ (full) ȯ // ̴. ̰ ī ȯ İ ī // (product)̶ ǹѴ. ι° ī ȯ // ̴. , ι° ù° ϰ Ǹ, ī // ִ. ι° ϸ, ī // ȴ. // : NPC(Normalized Projection Coordinates, ȭ ǥ) // // ī ȯ ǥ ī ǥ ȯѴ. , // ī ġѴ. ī ־ ù° // ܰ ۾ ȯ Ͽ ī ̴. // // 3ds max ǥκ Direct3D ǥ ⺻ ȯ: // // 3ds max: (Up, Front, Right) == (+Z, +Y, +X) // // Direct3D: (Up, Front, Right) == (+Y, +Z, +X) // // 3ds max κ Direct3D ǥ ȯ: // // 3ds max * ȯ = Direct3D // // [ x y z w ] * | +1 0 0 0 | = [ X Y Z W ] // | 0 0 +1 0 | // | 0 +1 0 0 | // | 0 0 0 +1 | // // Ʒ ȯ ۾ Ѵ. ǥ ȯ X // ȸ Ѵ. ǥ XY XZ ſ // ǵ ȯϱ ̴. Z ȣ ݴ ϸ RH LH // ȯŰ ȴ. , ȯ ǥ 3ds max κ ǥ // Direct3D ǥ ȯϰԲ ش.
Matrix3 camTM = Inverse(*invTM);
// ۽Ƽ() ÷ (4x3) (̰ // (0, 0, 0, 1) ؼ ִ). ° ߰Ͽ Z- ݴ . // ֳϸ, Direct3D ǥ踦 ϰ MAX ǥ踦 ϱ // ̴.
//
int ki, kj;
MRow *pcvm = camTM.GetAddr();
for (ki = 0; ki < 4; ki++) {
for (kj = 0; kj < 3; kj++) {
m_d3dViewXform.m[ki][kj] = pcvm[ki][kj];
}
}
// ° ÷ (۽Ƽ )
m_d3dViewXform.m[0][3] = m_d3dViewXform.m[1][3] = m_d3dViewXform.m[2][3] = 0.0f; m_d3dViewXform.m[3][3] = 1.0f;
// Z-( ° ÷) -1 Ͽ ǥ Direct3D ǥ // ȯѴ.
for (ki = 0; ki < 4; ki++) {
m_d3dViewXform.m[ki][2] *= -1.0f;
}
// Direct3D ī ȯ Ѵ. // // , MAX ü Ŀ MAX ī Ͽ MAX // ī ´. // // ̸ Direct3D ī ´. , Ʒ // и ʾҴ. //
MRow *pa = invTM->GetAddr();
for (ki = 0; ki < 4; ki++) {
float val = (float)(ki==3);
for (kj = 0; kj < 4; kj++) {
m_d3dProjXform.m[ki][kj] = pa[ki][0] * mat[0+kj] +
pa[ki][1] * mat[4+kj] +
pa[ki][2] * mat[8+kj] +
val * mat[12+kj];
}
}
// ī Ʒ и Ѵ. ̶, MAX NPC Z- // +1 -1 ε Direct3D NPC Z- 0 +1 // ̿Ѵ. // // ϱ ϵ, Direct3D Ʒ // . // // -켱(row-major order) ȴٴ . ̰ // (translate term) ° ġϰ ° // ġѴٴ ǹѴ. ̰ MAX, Direct3D, OpenGL ΰ ó // ϰ ϴ ̴. OpenGL -켱 // Ǿ , OpenGL ڵ -켱 ۾ ϵ // Ǿ ִ.
if (persp) {
// . Direct3D ī Ϲ : // // | 2n/(r-l) 0 0 0 | // | 0 2n/(t-b) 0 0 | // | (r+l)/(r-l) (t+b)/(t-b) f/(f-n) 1 | // | 0 0 -fn/(f-n) 0 | // // Direct3D µ Ʒ Ѵ //
m_d3dProjXform.m[2][2] = yon*oneOverDepth;
m_d3dProjXform.m[2][3] = 1.0f;
m_d3dProjXform.m[3][2] = -(yon*hither*oneOverDepth);
m_d3dProjXform.m[3][3] = 0.0f;
} else {
// . Direct3D ī Ϲ : // // | 2/(r-l) 0 0 0 | // | 0 2/(t-b) 0 0 | // | 0 0 1/(f-n) 0 | // | (r+l)/(r-l) (t+b)/(t-b) -n/(f-n) 1 | // // Direct3D µ Ʒ Ѵ. //
m_d3dProjXform.m[2][2] = oneOverDepth; m_d3dProjXform.m[2][3] = 0.0f; m_d3dProjXform.m[3][2] = -(hither*oneOverDepth); m_d3dProjXform.m[3][3] = 1.0f; }
// ī ȯ
ptr_to_your_D3DDevice->SetTransform(D3DTS_VIEW, &m_d3dViewXform);
// ī ȯ
ptr_to_your_D3DDevice->SetTransform(D3DTS_PROJECTION, &m_d3dProjXform);