2013-08-23 28 views
13

Basit bir 3B motoru geliştiririm (API'nin herhangi bir kullanımı olmadan), sahneyi dünyaya başarılı bir şekilde dönüştürdüm ve mekanı görüntüledim ancak bakış açımı kullanarak sahneyi yansıtan bir sorunum var (görüş alanından) izdüşüm matrisi (OpenGL stili). Fov, yakın ve uzak değerler hakkında emin değilim ve aldığım sahne çarpıtılmış. Birisi örnek kodlar ile perspektif izdüşümü matrisini nasıl oluşturup kullanacağımı bana yönlendirirse umarım. Herhangi bir yardım için şimdiden teşekkür ederiz.Perspektif izdüşümü matrisi oluşturma (API yok)

matris oluşturma:

double f = 1/Math.Tan(fovy/2); 
return new double[,] { 

    { f/Aspect, 0, 0, 0 }, 
    { 0, f, 0, 0 }, 
    { 0, 0, (Far + Near)/(Near - Far), (2 * Far * Near)/(Near - Far) }, 
    { 0, 0, -1, 0 } 
}; 

matris kullanımı:

foreach (Point P in T.Points) 
{  
    . 
    .  // Transforming the point to homogen point matrix, to world space, and to view space (works fine) 
    .  

    // projecting the point with getProjectionMatrix() specified in the previous code :  

    double[,] matrix = MatrixMultiply(GetProjectionMatrix(Fovy, Width/Height, Near, Far) , viewSpacePointMatrix); 

    // translating to Cartesian coordinates (from homogen): 

    matrix [0, 0] /= matrix [3, 0]; 
    matrix [1, 0] /= matrix [3, 0]; 
    matrix [2, 0] /= matrix [3, 0]; 
    matrix [3, 0] = 1; 
    P = MatrixToPoint(matrix); 

    // adjusting to the screen Y axis: 

    P.y = this.Height - P.y; 

    // Printing... 
} 
+0

http://www.scratchapixel.com/lessons/3d-basic-rendering:

Bu seferki sağ/sol/üst/alt/(OpenGL kullanılan) uzak/yakın parametrelerine dayalıdır/perspektif ve ortografik yansıtma matrisi Ayrıca önceki dersleri de öneriyorum (projeksiyon noktaları ve 3D görüntüleme). – user18490

cevap

23

aşağıdakı perspektif projeksiyonu matrisinin tipik implemenation olup. Burada Ve her şeyi OpenGL Projection Matrix

void ComputeFOVProjection(Matrix& result, float fov, float aspect, float nearDist, float farDist, bool leftHanded /* = true */) 
{ 
    // 
    // General form of the Projection Matrix 
    // 
    // uh = Cot(fov/2) == 1/Tan(fov/2) 
    // uw/uh = 1/aspect 
    // 
    // uw   0  0  0 
    // 0  uh  0  0 
    // 0   0  f/(f-n) 1 
    // 0   0 -fn/(f-n) 0 
    // 
    // Make result to be identity first 

    // check for bad parameters to avoid divide by zero: 
    // if found, assert and return an identity matrix. 
    if (fov <= 0 || aspect == 0) 
    { 
     Assert(fov > 0 && aspect != 0); 
     return; 
    } 

    float frustumDepth = farDist - nearDist; 
    float oneOverDepth = 1/frustumDepth; 

    result[1][1] = 1/tan(0.5f * fov); 
    result[0][0] = (leftHanded ? 1 : -1) * result[1][1]/aspect; 
    result[2][2] = farDist * oneOverDepth; 
    result[3][2] = (-farDist * nearDist) * oneOverDepth; 
    result[2][3] = 1; 
    result[3][3] = 0; 
} 
+0

Çok yardımcı, teşekkürler –

+0

Üzgünüz ama burada ve burada ne? Kullanıcı genişliği ve kullanıcı yüksekliği? – ReX357

+2

@ ReX357 uw = yakın/sağ ve uh = yakın/üst, sağ taraftaki planın üst koordinatlarının sağ üst ve sağ üst koordinatlarının koordinatları. Yukarıdaki perspektif projeksiyonu simetrik olduğundan, yani sağ = = ufuk genişliğinin yarısı ve üst = dikey yüksekliğin yarısı, sonra uw/uh = üst/sağ = yükseklik/genişlik = 1/görünüm –

0

yararlı olabilecek diğer bir işlevi açıklamak için iyi bir bağlantıdır.

static void test(){ 
    float projectionMatrix[16]; 

    // width and height of viewport to display on (screen dimensions in case of fullscreen rendering) 
    float ratio = (float)width/height; 
    float left = -ratio; 
    float right = ratio; 
    float bottom = -1.0f; 
    float top = 1.0f; 
    float near = -1.0f; 
    float far = 100.0f; 

    frustum(projectionMatrix, 0, left, right, bottom, top, near, far); 

} 

static void frustum(float *m, int offset, 
        float left, float right, float bottom, float top, 
        float near, float far) { 

    float r_width = 1.0f/(right - left); 
    float r_height = 1.0f/(top - bottom); 
    float r_depth = 1.0f/(far - near); 
    float x = 2.0f * (r_width); 
    float y = 2.0f * (r_height); 
    float z = 2.0f * (r_depth); 
    float A = (right + left) * r_width; 
    float B = (top + bottom) * r_height; 
    float C = (far + near) * r_depth; 
    m[offset + 0] = x; 
    m[offset + 3] = -A; 
    m[offset + 5] = y; 
    m[offset + 7] = -B; 
    m[offset + 10] = -z; 
    m[offset + 11] = -C; 
    m[offset + 1] = 0.0f; 
    m[offset + 2] = 0.0f; 
    m[offset + 4] = 0.0f; 
    m[offset + 6] = 0.0f; 
    m[offset + 8] = 0.0f; 
    m[offset + 9] = 0.0f; 
    m[offset + 12] = 0.0f; 
    m[offset + 13] = 0.0f; 
    m[offset + 14] = 0.0f; 
    m[offset + 15] = 1.0f; 

}