Практический метод представления круглых форм в перспективе? - PullRequest
2 голосов
/ 04 февраля 2011

Не совсем уверен, должно ли это относиться к переполнению стека, но здесь идет.

Я создаю простую версию крестики-нолики в 3D с использованием объекта HTML5 <canvas>. Первый игрок использует символ креста, тогда как второй игрок использует символ круга. Дело в том, что я не уверен, как поставить круглые формы в перспективу.

В настоящее время я использую метод создания правильного многоугольника с максимально возможным количеством углов (до некоторой степени), чтобы имитировать круг, рисуя прямые линии между этими точками. Координаты этих точек (углы) я рассчитал, используя синус / косинус.

Использование 6 углов:

enter image description here

Использование 50 углов (выглядит как круг достаточно хорошо):

enter image description here

Это хорошо работает, но для подделки круга требуется немало очков. Более того, если бы я создал мяч, у меня было бы больше проблем. Например, картина в Википедии показывает, что даже с большим количеством точек она все равно будет иметь довольно «блочную» поверхность: http://en.wikipedia.org/wiki/File:Sphere_wireframe.svg

Мне было интересно, есть ли способ сделать круг в перспективе более эффективным, возможно, без точек, чтобы можно было более реалистично создавать реалистично выглядящие круглые формы.

Заранее спасибо за любые предложения.

Ответы [ 3 ]

2 голосов
/ 05 февраля 2011

Ваша полигональная аппроксимация круга - практический путь. Очень просто вычислить координаты и применить к ним преобразование перспективы. Возможно, вам следует придерживаться этого решения.

Тем не менее, рассматриваемая вами кроличья нора ОЧЕНЬ крута, если вы увлекаетесь математическими вещами. Оказывается, что все квадрик поверхности - включая сферы и эллипсы - могут быть представлены с матрицей 4x4. Кроме того, после преобразования в формат 4x4 вы можете применить все стандартные матрицы преобразования 4x4 (это не просто умножение). IIRC вы даже можете применить к ним перспективное преобразование, и в результате вы все равно получите квадратичную поверхность. Теперь это не совсем помогает вам с 2D-фигурами в 3D-мире. Однако, поскольку круг - это пересечение цилиндра и плоскости, и оба они могут быть преобразованы, решение вашей проблемы должно быть.

Вот ссылка, описывающая представление и преобразования квадрик

Как вы показали, перспективная проекция круга на земле часто представляет собой вращающийся эллипс в пространстве экрана. У меня нет метода преобразования, но я верю, что он существует и более сложен, чем тот, который у вас есть сейчас.

1 голос
/ 10 октября 2014

Это заняло у меня несколько часов, но я окончательно разработал все уравнения и демонстрационный пример кода SVG: http://jsfiddle.net/6b8oLhz0/9/ Я использовал http://mathworld.wolfram.com/Ellipse.html для вычисления центра, радиусов и вращения осиучитывая только это уравнение.Самая интересная часть кода, возможно, такая:

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);
}
1 голос
/ 07 февраля 2011

Круг, если смотреть в перспективе, является эллипсом. Вот объяснение .

...