2011-02-04 2 views
2

스택 오버플로에 속해야하는지 확실하지 않지만 여기에 있습니다.원형 모양을 원근감있게 보여주는 실용적인 방법은 무엇입니까?

HTML5 <canvas> 개체를 사용하여 3D로 tic-tac-toe의 간단한 버전을 만들고 있습니다. 첫 번째 플레이어는 십자 기호를 사용하고 두 번째 플레이어는 원 기호를 사용합니다. 핵심은 원의 모양을 원근감있게 표현하는 방법을 모르겠다는 것입니다.

현재, 내가 사용하고있는 방법은 가능한 한 많은 각도로 (어느 정도까지) 해당 점 사이에서 직선을 그려 원을 가짜로 만드는 것입니다. 사인/코사인을 사용하여 계산 한 이러한 점 (각도)의 좌표입니다.

사용 6 각도 : 50 개 각도를 사용

enter image description here

(충분히 원 모양) :

enter image description here

이 잘 작동하지만,이 점을 꽤 많이 필요 서클을 멋지게 가짜로 만들려고. 게다가, 공을 만들면 더 어려워 질 것입니다. 예를 들어, 위키 피 디아의 그림은 많은 점을 가지고도 여전히 '뭉툭한'표면을 가지고 있음을 보여줍니다. http://en.wikipedia.org/wiki/File:Sphere_wireframe.svg

원을보다 효과적으로 배치 할 수있는 방법이 있는지 궁금합니다. , 아마 점없이, 실제적인보기 둥근 모양을 실제적인 방법으로 창조 할 수있을 것입니다.

미리 제안 해 주셔서 감사합니다.

+1

저는 대답이 없지만 이것은 확실히 StackOverflow 질문입니다. 그리고 좋은 것도 있습니다. 매우 유용한 그래픽입니다. – MusiGenesis

답변

2

원의 다각형 근사가 실제적인 방법입니다. 좌표를 계산하고 원근감 변환을 적용하는 것은 매우 간단합니다. 당신은 그 해결책에 충실해야합니다.

당신이 생각하고있는 토끼 구멍은 수학적인 것들이면 아주 멋집니다. 구체 및 타원을 포함한 모든 2 차 표면은 4x4 매트릭스로 나타낼 수 있습니다. 뿐만 아니라 한 번 4x4로 변환하면 모든 표준 4x4 변환 행렬을 적용 할 수 있습니다 (곱셈이 아닌). IIRC를 사용하면 투시 변환을 적용 할 수 있으며 그 결과는 여전히 2 차 표면입니다. 이제는 3D 세계에서 2D 모양을 사용하는 데 도움이되지 않습니다. 그러나 원은 원통과 평면의 교차점이며 둘 다 변형 될 수 있으므로 문제에 대한 해결책이 있어야합니다. 당신이 보여준 것처럼

Here is a link describing the representation and transformations of quadrics

, 지상에 원의 원근 투영은 종종 화면 공간에서 회전 타원이다. 나는 변형 방법이 없지만, 현재 존재하는 것보다 더 복잡하고 복잡하다고 믿습니다.

+0

답장과 링크를 제공해 주셔서 감사합니다. – pimvdb

1

원은 원근감으로 보았을 때 타원입니다. Here's an explanation.

+0

나는 항상 그것이 계란 모양 일 것이라고 생각했다. 뷰어에 더 가까운 부분이 더 크기 때문에. 어쨌든, 나는 틀렸어, 링크 덕분에. – pimvdb

1

그것은 나에게 몇 시간이 걸렸지 만 나는 finnally 모든 방정식과 SVG 코드 데모 개발했습니다 : 나는 센터, 반경을 계산하는 http://mathworld.wolfram.com/Ellipse.html을 사용했습니다 http://jsfiddle.net/6b8oLhz0/9/ , 그리고 축의 회전 그것은 단지 방정식의 주어진. 코드의 가장 흥미로운 부분은 아마도 다음과 같습니다.

function ellipseBy3DCircle(circle){ 
    var r=circle.radius; 
    var n=circle.normal; 
    var c=circle.center; 
    //Let (u,v) be a point of the Ellipse. 
    //Which point of the circle it represents? 
    //This 3-D point must have a form of (u*z,v*z,z) for some z, 
    //bacause it lays on a ray from observer (0,0,0) through (u,v,1) on the screen. 
    //A circle is an intersection of a plane with a sphere. 
    //So we have two conditions for our point : 
    //1) it has to belong to the plane given by the center and normal of the circle: 
    //(u*z-c.x)*n.x+ (v*z-c.y)*n.y + (z-c.z)*n.z = 0 
    //2) it has to belong to the sphere given by the center and radius 
    //(u*z-c.x)^2 + (v*z-c.y)^2 + (z-c.z)^2 = 0 
    //The first equation alows us to express z in terms of u,v and constants: 
    //z = (c.x*n.x+c.y*n.y+c.z*n.z)/(u*n.x+v*n.y+n.z) 
    //  ^^^^^^^^^^^^ s ^^^^^^^^^ ^^^^ t(u,v) ^^^^ 
    var s=c.x*n.x+c.y*n.y+c.z*n.z; 
    //t(u,v)=u*n.x+v*n.y+n.z 
    //The second equation gives us: 
    //zz(uu+vv+1)-2z(u*c.x+v*c.y+z*c.z)+c.x^2+c.y^2+c.z^2-r^2 = 0 
    //         ^^^^^^^^ H ^^^^^^^^^ 
    var H=c.x*c.x+c.y*c.y+c.z*c.z-r*r; 
    //Recall however, that z has u and v in denominator which makes it hard to solve/simplify. 
    //But z=s/t(u,v), so let us multiply both sides by t(u,v)^2 : 
    //ss*(uu+vv+1)-2*s*t(u,v)*(u*c.x+v*c.y+c.z)+t(u,v)^2*H=0 
    //ss*uu+ss*vv+ss-2*s*(u*n.x+v*n.y+n.z)*(u*c.x+v*c.y+c.z)+(u*n.x+v*n.y+n.z)*(u*n.x+v*n.y+n.z)*H=0 
    //By regrouping terms so as to match the ax^2+2bxy+cy^2+2dx+2fy+g = 0 formula, we get: 
    var A=s*s+H*n.x*n.x-2*s*n.x*c.x; 
    var B=H*n.x*n.y-s*n.x*c.y-s*n.y*c.x; 
    var C=s*s+H*n.y*n.y-2*s*n.y*c.y; 
    var D=H*n.x*n.z-s*n.x*c.z-s*n.z*c.x; 
    var F=H*n.y*n.z-s*n.y*c.z-s*n.z*c.y; 
    var G=s*s+H*n.z*n.z-2*s*n.z*c.z; 

    return ellipseByEquation(A,B,C,D,F,G); 
}