2017-11-06 1 views
4

오브젝트를 그려서 회전시키는 방법 비스듬한 정면 (dimetric) 제대로 투영합니까?오브젝트를 그리고 비스듬히 정면 투영으로 회전하는 방법

투사의 그림 :

Oblique frontal projection

나는 이미 그것을 수행하는 프로그램 (파스칼 그래프 유닛)을했습니다,하지만 난 그것을 잘못 객체를 그립니다 있다고 생각합니다.

program p7test; 

uses PtcCrt, PtcGraph; 

type 
    TPixel = record 
    x, y, z: real; 
    end; 
    TModel = record 
    p: array [ 1..8 ] of TPixel; 
    end; 
    TCenter = record 
    xc, zc: integer; 
    end; 

var 
    Driver, Mode: integer; 
    c: char; 
    s: string; 
    ns, rx, ry, rz, ra, m_l, m_w, m_h, m_l_d, m_w_d, m_h_d: integer; 
    model_d, model: TModel; 
    center: TCenter; 

    procedure LineXYZ(sp_t, ep_t: TPixel; center_t: TCenter); 
    var 
    x1, y1, x2, y2: real; 
    begin 
    x1 := sp_t.x - sin(pi/4) * sp_t.y/2; 
    y1 := sp_t.z - sin(pi/4) * sp_t.y/2; 
    x2 := ep_t.x - sin(pi/4) * ep_t.y/2; 
    y2 := ep_t.z - sin(pi/4) * ep_t.y/2; 
    Line(
     round(center_t.xc - x1), 
     round(center_t.zc - y1), 
     round(center_t.xc - x2), 
     round(center_t.zc - y2) 
    ); 
    end; 

    procedure DrawModel(model_t: TModel; center_t: TCenter); 
    var 
    i: integer; 
    begin 
    LineXYZ(model_t.p[ 1 ], model_t.p[ 2 ], center_t); 
    LineXYZ(model_t.p[ 2 ], model_t.p[ 3 ], center_t); 
    LineXYZ(model_t.p[ 3 ], model_t.p[ 4 ], center_t); 
    LineXYZ(model_t.p[ 4 ], model_t.p[ 1 ], center_t); 
    LineXYZ(model_t.p[ 5 ], model_t.p[ 6 ], center_t); 
    LineXYZ(model_t.p[ 6 ], model_t.p[ 7 ], center_t); 
    LineXYZ(model_t.p[ 7 ], model_t.p[ 8 ], center_t); 
    LineXYZ(model_t.p[ 8 ], model_t.p[ 5 ], center_t); 
    LineXYZ(model_t.p[ 1 ], model_t.p[ 5 ], center_t); 
    LineXYZ(model_t.p[ 2 ], model_t.p[ 6 ], center_t); 
    LineXYZ(model_t.p[ 3 ], model_t.p[ 7 ], center_t); 
    LineXYZ(model_t.p[ 4 ], model_t.p[ 8 ], center_t); 
    end; 

    function RotateZ(model_t: TModel; angle: real): TModel; 
    var 
    x, y: real; 
    i: integer; 
    begin 
    angle := angle * pi/180; 
    for i := 1 to 8 do 
    begin 
     x := model_t.p[ i ].x; 
     y := model_t.p[ i ].y; 
     model_t.p[ i ].x := x * cos(angle) - y * sin(angle); 
     model_t.p[ i ].y := y * cos(angle) + x * sin(angle); 
    end; 
    RotateZ := model_t; 
    end; 

    function RotateY(model_t: TModel; angle: real): TModel; 
    var 
    x, z: real; 
    i: integer; 
    begin 
    angle := angle * pi/180; 
    for i := 1 to 8 do 
    begin 
     x := model_t.p[ i ].x; 
     z := model_t.p[ i ].z; 
     model_t.p[ i ].x := x * cos(angle) - z * sin(angle); 
     model_t.p[ i ].z := z * cos(angle) + x * sin(angle); 
    end; 
    RotateY := model_t; 
    end; 

    function RotateX(model_t: TModel; angle: real): TModel; 
    var 
    y, z: real; 
    i: integer; 
    begin 
    angle := angle * pi/180; 
    for i := 1 to 8 do 
    begin 
     y := model_t.p[ i ].y; 
     z := model_t.p[ i ].z; 
     model_t.p[ i ].y := y * cos(angle) - z * sin(angle); 
     model_t.p[ i ].z := z * cos(angle) + y * sin(angle); 
    end; 
    RotateX := model_t; 
    end; 

    function RotateXYZ(model_t: TModel; rx_t, ry_t, rz_t: integer): TModel; 
    begin 
    model_t := RotateX(model_t, rx_t); 
    model_t := RotateY(model_t, ry_t); 
    model_t := RotateZ(model_t, rz_t); 
    RotateXYZ := model_t; 
    end; 

begin 
    Driver := D8bit; 
    Mode := m800x600; 
    InitGraph(Driver, Mode, ''); 
    ra := 2; 
    if (GraphResult <> GrOk) then WriteLn('640x480x256''s not supported') else 
    begin 
    ClearDevice; 
    center.xc := (GetMaxX div 2) + 1; 
    center.zc := (GetMaxY div 2) + 1; 
    m_l_d := 200; m_w_d := 200; m_h_d := 200; 
    m_l := m_l_d; m_w := m_w_d; m_h := m_h_d; 
    rx := -26; ry := 6; rz := 16; 

    model_d.p[ 1 ].x := - m_l/2; model_d.p[ 1 ].y := - m_w/2; model_d.p[ 1 ].z := - m_h/2; 
    model_d.p[ 2 ].x := - m_l/2; model_d.p[ 2 ].y := m_w/2; model_d.p[ 2 ].z := - m_h/2; 
    model_d.p[ 3 ].x := m_l/2; model_d.p[ 3 ].y := m_w/2; model_d.p[ 3 ].z := - m_h/2; 
    model_d.p[ 4 ].x := m_l/2; model_d.p[ 4 ].y := - m_w/2; model_d.p[ 4 ].z := - m_h/2; 
    model_d.p[ 5 ].x := - m_l/2; model_d.p[ 5 ].y := - m_w/2; model_d.p[ 5 ].z := m_h/2; 
    model_d.p[ 6 ].x := - m_l/2; model_d.p[ 6 ].y := m_w/2; model_d.p[ 6 ].z := m_h/2; 
    model_d.p[ 7 ].x := m_l/2; model_d.p[ 7 ].y := m_w/2; model_d.p[ 7 ].z := m_h/2; 
    model_d.p[ 8 ].x := m_l/2; model_d.p[ 8 ].y := - m_w/2; model_d.p[ 8 ].z := m_h/2; 

    model := RotateXYZ(model_d, rx, ry, rz); 
    SetColor(2); DrawModel(model, center); 
    SetColor(12); 
    Str(rx, s); OutTextXY(2, 2, 'rx=' + s); 
    Str(ry, s); OutTextXY(2, 12, 'ry=' + s); 
    Str(rz, s); OutTextXY(2, 22, 'rz=' + s); 

    repeat Delay(100) until KeyPressed; 
    if ns = 0 then ns := 1 else ns := 0; 
    ReadKey; 
    repeat 
     c := ReadKey; 
     case c of 
     #113: begin rx := rx - ra; model := RotateXYZ(model_d, rx, ry, rz); end; 
     #101: begin rx := rx + ra; model := RotateXYZ(model_d, rx, ry, rz); end; 
     #119: begin ry := ry - ra; model := RotateXYZ(model_d, rx, ry, rz); end; 
     #115: begin ry := ry + ra; model := RotateXYZ(model_d, rx, ry, rz); end; 
     #97: begin rz := rz - ra; model := RotateXYZ(model_d, rx, ry, rz); end; 
     #100: begin rz := rz + ra; model := RotateXYZ(model_d, rx, ry, rz); end; 
     #117: begin 
      rx := 0; ry := 0; rz := 0; 
      model := RotateXYZ(model_d, rx, ry, rz); 
     end; 
     end; 
     ClearDevice; 

     SetColor(2); DrawModel(model, center); 
     SetColor(12); 
     Str(rx, s); OutTextXY(2, 2, 'rx=' + s); 
     Str(ry, s); OutTextXY(2, 12, 'ry=' + s); 
     Str(rz, s); OutTextXY(2, 22, 'rz=' + s); 

     if ns = 0 then 
     begin 
     SetActivePage(0); 
     SetVisualPage(1) 
     end 
     else 
     begin 
     SetActivePage(1); 
     SetVisualPage(0) 
     end; 
     if ns = 0 then ns := 1 else ns := 0; 
    until c = #27; 
    CloseGraph; 
    end; 
end. 

하면 물체를 회전 키 R S D Q EW 사용할 수있다. 이 아래처럼 보일 것 아닌가요

Object rotation 1

: 당신이 그림에서 보는 바와 같이

그래서 아래에 당신이 그것을보고있는 몇 가지 문제가 그리고 그것은 약간 긴거야?

Object rotation 2

나는이에 LineXYZ 라인을 변경 시도했다 :

x1 := sp_t.x - (sp_t.y/2); 
y1 := sp_t.z - (sp_t.y/2); 
x2 := ep_t.x - (ep_t.y/2); 
y2 := ep_t.z - (ep_t.y/2); 

그러나 나는 그것이 옳지 않다고 생각한다.은 Z 올바르게 (회전 *)와 같은 기능을 Y 좌표


암 I은 X, 회전? Btw 주요 문제는 LineXYZ (y 좌표 부분) 과 같은 것으로 생각합니다.이 유형의 투영에 개체를 그리는 방법은 무엇입니까?

감사합니다.

안부, V7

+1

약간의 신장은 엄격하게 시각적 환상, 물론입니다. [ "perspective"drawing] (https://www.math.utah.edu/~treiberg/Perspect/Perspect.htm) 기법을 사용하고 가상의 초점을 선택하고 해당 수정으로 좌표를 계산해야합니다. – lurker

+0

친애하는 @lurker 여기 보이는대로 https://media.giphy.com/media/3ohs85jCAleB5LwHUQ/giphy.gif 환상이 없습니다. 그렇지 않니? 그럼 왜 내 코드에 들어 있죠? 그것은 ** y/2 ** 때문입니까? 그래서 .. 나는 이것이 환상이 아니라고 생각합니다. 다만 그것을 평가하기 위하여 다만 시도하십시오 * right * 그리고 당신은 무슨 일이 일어날 지 볼 것이다. –

+0

길게 보이는 뒤쪽 가장자리는 전경의 가장자리와 실제로 길이가 동일하기 때문에 환상이라고합니다. 나는 당신의 이미지를 스냅하고 그것을 측정했다. 그러나 뒤쪽 가장자리는 원근법 때문에 더 길게 보입니다. 눈/뇌는 그 물체를 3D 입방체로 해석하지만 길이는 그 개념을지지하기에는 적합하지 않습니다. 내가 제공 한 링크에 설명 된 원근법을 사용하여 적절한 깊이와 비율의 환상을 만들어야합니다. – lurker

답변

2

는 아래처럼 보일 것 아닌가요?

  1. 귀하의 X 축 잘못
  2. 를 지시한다 : 당신의 축 135-90

    당신의 코드는 두 가지를 제외하고, 올바른 동안

하지

, GIF 아래 90-90 투사이며,
  • cos 대신 sin을 사용하고 각도는 pi/4이지만 각도를 변경하려는 경우 ...
  • 귀하의 코드 :

    x1 := sp_t.x - sin(pi/4) * sp_t.y/2; 
    y1 := sp_t.z - sin(pi/4) * sp_t.y/2; 
    x2 := ep_t.x - sin(pi/4) * ep_t.y/2; 
    y2 := ep_t.z - sin(pi/4) * ep_t.y/2; 
    

    가되어야한다 나머지에서

    x1 := -sp_t.x - cos(pi/4) * sp_t.y/2; 
    y1 := sp_t.z - sin(pi/4) * sp_t.y/2; 
    x2 := -ep_t.x - cos(pi/4) * ep_t.y/2; 
    y2 := ep_t.z - sin(pi/4) * ep_t.y/2; 
    

    이 렌더링은 올바른 것입니다. @lurker 주석에 대하여

    Live Demo


    :
    여기 관점 환상을 해결하는 이유는 (- 동등하게 모든 시청자를 보상하는 것은 불가능 그것을 뭔가 personificated 것).

    이 지프는이 환상 효과를 보여줍니다
    Illusion Demonstration

    +1

    고맙습니다. @vp_arth ... 정말 도움이되었습니다. –

    +0

    * 원근감 환상을 여기에서 수정해야 할 이유는 없습니다 (이는 개인적인 것으로 모든 시청자에게 똑같이 보상 할 수 없음). * 사실입니다. 그러나이 경우 하나의 뷰어/관점 만 있으므로 보상 될 수 있습니다. – lurker

    관련 문제