Конференция "Игры" » Сфера [любая, любая]
 
  • tButton © (15.02.10 13:20) [0]
    задался вопросом построения сферы типа Geosphere (Gsphere) в 3DMax'е
    извел тонну бумаги и замучал в усмерть гугл, но так ни к чему и не пришел
    скорее всего я не правильно задавал вопрос =)

    была конечно мысль начать с Октаэра
    после чего построить вершины в центре каждой грани...
    привести растояние от центра до новой вершины к радиусу сферы
    и перестроить грани...
    не то. по экватору остается все те же 4 ребра
  • tButton © (15.02.10 13:25) [1]
    была также мысль вычислить угловой размер грани
    но как их разместить по поверхности сферы не понятно

    т.е. если я изволю 12 граней по экватору
    угловой размер грани будет равен 30 градусам
    это дает нам еще 4 параллели (по две в направлении от экватора к каждому полюсу)
    сколько граней должно быть на первой от экватора параллели?
    каково угловое расстояние между экватором и первой параллелью
    что-то я сомневаюьс в 30 градусах,
    скорее - 30 * sqrt(3) / 2 градусов...
    но тоже не факт.
  • tButton © (16.02.10 16:25) [2]
    вот что насочинял по поводу вершин
    n - количество слоев на которое будем делить сферу вдоль вертикальной оси, он же уровень детализации
    R - радиус сферы
    α - угловой размер хорды грани (тот, который желаем)
    α = π / n
    l - длина грани на экваторе
    l = 2 * π * R * α / π = 2 * R * α
    P - номер параллели по направлению от экватора к северному полюсу (0 - экватор, n /2 - северный полюс, -n / 2 - южный полюс)
    M - количество граней на паралелли P
    M = round(cos(α * P) * 2 * π * R / l)
    l' - длина грани на параллели P (значение контрольное, на практике ненужное)

    прогнал я все это дело через calc
    и в целом доволен результатами
    в частности - при любом из опробованых n, последняя перед полюсом параллель имеет шесть граней (тестировалось для n от 10 и выше)

    теперь осталось разобраться с триангуляцией всей этой хренотени =)
  • Jeer © (17.02.10 22:31) [3]
    Ты продолжай разговаривать..
    Кому то - как снотворное, однозначно.
  • @!!ex © (17.02.10 22:54) [4]
    Я бы помог, но бошка не варит совершенно.
    На Jeer внимания не обращяй, он зол сегодня.
    практика показывать решение своих же задач весьма полезна.
  • Franzy (18.02.10 14:55) [5]
    Не знаю, что за геосфера в 3DMAX, поэтому не уверен, то или не то...
    У меня была задача о разбиении сферы на правильные треугольники. На входе - радиус, координаты центра сферы и желаемая длина ребра треугольников. На выходе - список координат узлов и список треугольников. Нужно?
  • Franzy (18.02.10 15:08) [6]
    Вот код. Выходные данные хранятся в массивах
     gs_n_tris : longint; //кол-во треуг.
     gs_n_nodes : longint; //кол-во узлов
     gs_node : array of TPoint3D; //коордианты узлов
     gs_tri : array of array [1..3] of longint; //список треугольников. Узлы всегда обходятся против часовой стрелки

    Пользуйтесь!

    unit GridderSphere;

    interface

    uses Math;

    const pi2 = 0.5*pi;
         pi5 = 0.4*pi;
         pi6 = pi/6;
         pi10 = 0.2*pi;
         gs_eps = 1e-10;
         dvapi =2*pi;

    type

     TGeoCords = record
      lat, lon : double;
     end;

     TPoint3D = record
        x,y,z : double;
     End;

    var
     gs_n_tris : longint;
     gs_n_nodes : longint;
     gs_node : array of TPoint3D;
     gs_nodep : array [1..12] of TGeoCords;
     gs_tri : array of array [1..3] of longint;

    procedure FormSphere(const cx,cy,cz,rad,h : double);

    implementation

    //uses GridderMain;

    procedure FormSphere(const cx,cy,cz,rad,h : double);
    var i,nt,nn : longint;
       tlevel : longint;
         //tlevel = 1 -> 20*1 triangles
         //       = 2 -> 20*4  =  80 tri
         //       = 3 -> 20*9  = 180 tri
         //       = 4 -> 20*16 = 320 tri etc
       dtemp : double;
       ind : array of array of longint;

       edge : array [1..30] of array of longint;
       n_edges : longint;
       ed1,ed2,ed3 : array of longint;

       ////////////////////////
      function GetWPoint(pq1,pq2 : TPoint3d; w: double): TPoint3d;
    var w1,tt:double;
       r,r1,r2: TPoint3d;
    begin
     w1:=1-w;

     r1.x:=pq1.x-cx;
     r1.y:=pq1.y-cy;
     r1.z:=pq1.z-cz;

     r2.x:=pq2.x-cx;
     r2.y:=pq2.y-cy;
     r2.z:=pq2.z-cz;

     r.x:=w*r2.x+w1*r1.x;
     r.y:=w*r2.y+w1*r1.y;
     r.z:=w*r2.z+w1*r1.z;

     tt:=rad/sqrt(sqr(r.x)+sqr(r.y)+sqr(r.z));

     r.x:=r.x*tt;
     r.y:=r.y*tt;
     r.z:=r.z*tt;

     r.x:=cx+r.x;
     r.y:=cy+r.y;
     r.z:=cz+r.z;

     Result:=r;

    end;

    /////////////////

      function GetCoords(const ln,lt : double): TPoint3D;
       var p : tpoint3d;
           rr : double;
       begin
         rr:=rad*cos(lt);
         p.x:=cx+rr*cos(ln);
         p.y:=cy+rr*sin(ln);
         p.z:=cz+rad*sin(lt);
         Result:=p;
       end;

      procedure TesselateEdge(n1,n2:longint);
      var i:longint;

      begin
        inc(n_edges);
        edge[n_edges]:=nil;
        SetLength(edge[n_edges],tlevel+1);
        edge[n_edges][0]:=n1;
        edge[n_edges][tlevel]:=n2;

        for i:=1 to tlevel-1 do
         begin
           inc(nn);
           edge[n_edges][i]:=nn;
           gs_node[nn]:=GetWPoint(gs_node[n1],gs_node[n2],i/tlevel);
         end;

      end;

      procedure TesselateTriangle(const n1,n2,n3 : longint);
       var i,j,e1,e2,e3: longint;

       function getEdge(const nn1,nn2:longint): longint;
         var i: longint;
         begin
           for i:=1 to 30 do
            begin
             if (edge[i][0]=nn1) and (edge[i][tlevel]=nn2) then
               begin
                 Result:=i;
                 exit;
               end;
             if (edge[i][0]=nn2) and (edge[i][tlevel]=nn1) then
               begin
                 Result:=-i;
                 exit;
               end;
            end;
         end;

      begin

       
        e1:=GetEdge(n1,n2);
        e2:=GetEdge(n1,n3);
        e3:=GetEdge(n2,n3);

        if e1>0 then
         for i:=0 to tlevel do
          ed1[i]:=edge[e1][i]
        else
         for i:=0 to tlevel do
          ed1[i]:=edge[-e1][tlevel-i];

        if e2>0 then
         for i:=0 to tlevel do
          ed2[i]:=edge[e2][i]
        else
         for i:=0 to tlevel do
          ed2[i]:=edge[-e2][tlevel-i];

        if e3>0 then
         for i:=0 to tlevel do
          ed3[i]:=edge[e3][i]
        else
         for i:=0 to tlevel do
          ed3[i]:=edge[-e3][tlevel-i];

        for i:=2 to tlevel-1 do
         for j:=1 to i-1 do
          begin
            inc(nn);
            gs_node[nn]:=GetWPoint(gs_node[ed1[i]],gs_node[ed2[i]],j/i);
            ind[i,j]:=nn;
          end;

         for i:=0 to tlevel do
              ind[i,0]:=ed1[i];
         for i:=1 to tlevel do
              ind[i,i]:=ed2[i];
         for i:=1 to tlevel-1 do
              ind[tlevel,i]:=ed3[i];

         for i:=0 to tlevel-1 do
          begin
            for j:=0 to i do
             begin
               inc(nt);
               gs_tri[nt][1]:=ind[i,j];
               gs_tri[nt][2]:=ind[i+1,j];
               gs_tri[nt][3]:=ind[i+1,j+1];
             end;
            for j:=0 to i-1 do
             begin
               inc(nt);
               gs_tri[nt][1]:=ind[i,j];
               gs_tri[nt][2]:=ind[i+1,j+1];
               gs_tri[nt][3]:=ind[i,j+1];

             end;

          end;

      end;

    begin
     gs_n_tris :=0;
     gs_n_nodes :=0;
     gs_node :=nil;
     gs_tri :=nil;

     dtemp:=0.95*rad;

     tlevel:=ceil(dtemp/h);

     gs_n_tris := 20*sqr(tlevel);
     gs_n_nodes := 10*sqr(tlevel)+2;

     SetLength(gs_node,gs_n_nodes+1);
     SetLength(gs_tri,gs_n_tris+1);

     nt:=0;
     nn:=12;

     ind:=nil;
     SetLength(ind,tlevel+1);
     for i:=0 to tlevel do
      SetLength(ind[i],i+1);

     gs_nodep[1].lat:=pi2;
     gs_nodep[1].lon:=0;
     gs_nodep[2].lat:=-pi2;
     gs_nodep[2].lon:=0;
     for i:=0 to 4 do
      begin
        gs_nodep[i+3].lon:=i*pi5;
        gs_nodep[i+3].lat:=pi6;
      end;
     for i:=0 to 4 do
      begin
        gs_nodep[i+8].lon:=i*pi5+pi10;
        gs_nodep[i+8].lat:=-pi6;
      end;

     for i:=1 to 12 do
       gs_node[i]:=GetCoords(gs_nodep[i].lon,gs_nodep[i].lat);

     n_edges:=0;
     TesselateEdge(1,3);
     TesselateEdge(1,4);
     TesselateEdge(1,5);
     TesselateEdge(1,6);
     TesselateEdge(1,7);
     TesselateEdge(2,8);
     TesselateEdge(2,9);
     TesselateEdge(2,10);
     TesselateEdge(2,11);
     TesselateEdge(2,12);
     TesselateEdge(3,12);
     TesselateEdge(3,8);
     TesselateEdge(4,8);
     TesselateEdge(4,9);
     TesselateEdge(5,9);
     TesselateEdge(5,10);
     TesselateEdge(6,10);
     TesselateEdge(6,11);
     TesselateEdge(7,11);
     TesselateEdge(7,12);
     TesselateEdge(3,4);
     TesselateEdge(4,5);
     TesselateEdge(5,6);
     TesselateEdge(6,7);
     TesselateEdge(3,7);
     TesselateEdge(8,9);
     TesselateEdge(9,10);
     TesselateEdge(10,11);
     TesselateEdge(11,12);
     TesselateEdge(8,12);

     ed1:=nil;
     ed2:=nil;
     ed3:=nil;
     SetLength(ed1,tlevel+1);
     SetLength(ed2,tlevel+1);
     SetLength(ed3,tlevel+1);

     TesselateTriangle(1,7,3);
     TesselateTriangle(1,6,7);
     TesselateTriangle(1,5,6);
     TesselateTriangle(1,4,5);
     TesselateTriangle(1,3,4);
     TesselateTriangle(6,11,7);
     TesselateTriangle(7,11,12);
     TesselateTriangle(7,12,3);
     TesselateTriangle(3,12,8);
     TesselateTriangle(3,8,4);
     TesselateTriangle(4,8,9);
     TesselateTriangle(4,9,5);
     TesselateTriangle(5,9,10);
     TesselateTriangle(5,10,6);
     TesselateTriangle(6,10,11);
     TesselateTriangle(2,12,11);
     TesselateTriangle(2,8,12);
     TesselateTriangle(2,9,8);
     TesselateTriangle(2,10,9);
     TesselateTriangle(2,11,10);

    end;
    end.

  • tButton © (18.02.10 15:15) [7]

    > Franzy   (18.02.10 14:55) [5]

    да
    я думаю, что это

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

    возьмем два соседних ряда (параллели) вешин
    H1,H2,H3,H4,H5,H6
    L1,L2,L3,L4,L5,L6,L7,L8,L9
    в верхнем (H) ряду вершины будут расположены с интервалом 60 градусов
    в нижнем - 40

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

    построим треугольник от вершины L7
    положение L7 = 6 * 40 + 20 = 260 градусов
    положение L8 = 7 * 40 + 20 = 300 градусов
    какая вершина из верхнего ряда лучшим образом подойдет для завершения данного треугольника
    Ответ: та, чье положение в ряду >= 260 градусам, и та что ближе всего к этому значению
    поскольку ряд не имеет смещения, можно вычислить положение нашей вершины
    оно равно ceil(260 / 60) * 60 = 300
    что соответствует вершине H6
    проверим?
    предыдущая вершина H5 имеет положение 240 градусов и явно не подходит
    значит наш треугольник образуется вершинами L7-L8-H6

    но как быть с обратным ему рядом?
    вот с этим я пока не разобрался
  • tButton © (18.02.10 15:24) [8]

    > Franzy   (18.02.10 15:08) [6]

    анализирую, при беглом осмотре смутил лишь участок с предварительно прописаными входными данными функции

     TesselateEdge(1,3);
     TesselateEdge(1,4);
     ...
     TesselateEdge(11,12);
     TesselateEdge(8,12);

  • Franzy (18.02.10 15:51) [9]
    Идея алгоритма проста: берется икосаэдр (20-гранник из правильных треугольников) и каждая его грань делится на 4, 9, 16 ... и т.д. - сколько нужно -  треугольников. Причем узлы при этом проецируются на поверхность сферы. Получается очень красиво и аккуратно. Автокад со своими сферами курит в сторонке.
    Если смущает 20 команд по разбитию каждого ребра и каждой грани икосаэдра, можешь попробовать засунуть их в цикл. В один скорее всего не получится, придется использовать 4-5. На мой взгляд, овчинка выделки не стоит. Так вполне наглядно и, главное, надежно.
  • Franzy (18.02.10 15:56) [10]
    Вот картинка - пример того, что получается.
    http://slil.ru/28669800
  • 12 © (24.02.10 16:37) [11]
    я, наверное, не понимаю проблемы, но вот такое решение

    на шаре прочерчиваем параллели, на каждой параллели берем сколь угодно равноотстоящих точек и получаем прямоугольники с вершинами на параллелях шара. Устремляя колво параллелей и точек на каждой в бесконечность имеем шар.
  • @!!ex © (24.02.10 19:05) [12]
    > [11] 12 ©   (24.02.10 16:37)

    это не будет геосфера.
  • 12 © (25.02.10 09:22) [13]

    > это не будет геосфера.

    а как будет?
    В инете поискал определение - чего-то не то выдает


    > Вот картинка
    > http://slil.ru/28669800

    это - геосфера? Если да, то в чем разница?
  • @!!ex © (25.02.10 14:17) [14]
    > [13] 12 ©   (25.02.10 09:22)
    > это - геосфера? Если да, то в чем разница?

    Где там прямоугольники??
  • 12 © (25.02.10 16:00) [15]

    > Где там прямоугольники??

    нет их там. Там треугольники.
    т.е. геосфера - это то, что состоит из треугольников?
    если так, то прямоугольник это 2 треугольника..
  • @!!ex © (25.02.10 18:14) [16]
    > [15] 12 ©   (25.02.10 16:00)

    из равносторонних.
  • tButton © (26.02.10 09:24) [17]

    > в чем разница?

    в том, что геосфера не имеет явного сгущения абсолютно не нужных вершин у полюсов
  • tButton © (26.02.10 09:27) [18]
    спасибо товарищу Franzy
    идею я понял и насколько я понял,
    в принципе можно взять любой правильный многогранник,
    грани которого образованы равнобедренными треугольниками
    (да хоть бы и тетраэдр)
    разбить каждую грань на N-ое количество подобных треугольников
    и равноудалить вершины от центра сферы
    хорошая, годная методика
  • Franzy (05.03.10 15:23) [19]
    Таких многранников ровно три: тетраэдр, октаэдр и икосаэдр. И, кстати, не обольщайтесь: треугольники в моей сфере не правильные, а только близки к ним, хотя и весьма сильно. Это на плоскости если правильный треугольник поделить на 4 равных треугольника они тоже будут правильными. У сферической геометрии свои законы.
  • tButton © (12.03.10 02:41) [20]
    Совершенно верно, поэтому тесселяцию нужно делать перед сферизацией. Тогда, если исходный многогранник правильный, то и получившиеся треугольники будут правильными.
  • Franzy (12.03.10 13:52) [21]
    Нет, не будут. Они исказятся при проекции.
 
Конференция "Игры" » Сфера [любая, любая]
Есть новые Нет новых   [118488   +59][b:0][p:0.006]