Autor Wątek: Jeden wektor jak go sie obliczalo :P Frustum :S  (Przeczytany 2544 razy)

Offline ziomber

  • Użytkownik

  • Zbanowany
# Lipiec 03, 2007, 17:43:02


Po samej lewej stronie jest Wektor UP. Go chce wyliczyc, tylko nie pamietam jak i juz nie mam pomyslow :X

d to kierunek, w ktory patrzymy p - pozycja kamery, right sie wylicza z UP i d
Wsystkie kąty są podane (tzn. zeby było wiadomo gdzie patrzymy - to potrzebujemy 2 kątów)

Offline Mr. Spam

  • Miłośnik przetworów mięsnych

Offline 5corpio

  • Użytkownik

# Lipiec 03, 2007, 18:02:23
Nie czy myślę dobrze ale masz kąty ? To d policz sobię z trójkąta a UP policzysz jako wektor prostopadły do d ?

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Lipiec 03, 2007, 18:06:33
Te wszystkie wektory masz zapisane bezpośrednio w macierzy widoku, więc wystarczy je stamąd odczytać. W jaki dokładnie sposób są tam one zapisane, to już zależy od API graficznego, którego używasz. :)

.

  • Gość
# Lipiec 03, 2007, 18:14:23
no ale nie napisałeś co masz dane. troche to pytanie dziwne bo jak piszesz obsługę kamery to prawdopodobnie będziesz musiał samodzielnie określać wektor UP. ja tak robie korzystając z gluLookAt().

Offline ziomber

  • Użytkownik

  • Zbanowany
# Lipiec 03, 2007, 18:19:14
therealremi gdzie ty tu masz wylcizanie wektora UP ? zglupiales?
glulookat(old.x,old.y,old.z,old.x+SUPERPOINT.x,old.y-SUPERPOINT.y,old.z-SUPERPOINT.z,0,1,0);

Krzysiek K. dobra odpowiedz, musze tylko pomyslec - watpie ze cos z tego wyjdzie bo te 16 pozycji jest za bardzo smiesznych :S

Nawet sobie sprawy nei zdajesz jak mi sie nie chce pisać wizalizacji tych cyferek z macierzy :S ;[
« Ostatnia zmiana: Lipiec 03, 2007, 18:27:07 wysłana przez ziomber »

Offline revo

  • Użytkownik

# Lipiec 03, 2007, 18:25:43
therealremi gdzie ty tu masz wylcizanie wektora UP ? zglupiales?
glulookat(old.x,old.y,old.z,old.x+SUPERPOINT.x,old.y-SUPERPOINT.y,old.z-SUPERPOINT.z,0,1,0);

Krzysiek K. dobra odpowiedz, musze tylko pomyslec - watpie ze cos z tego wyjdzie bo te 16 pozycji jest za bardzo smiesznych :S

ziomber, zgłupiałeś? ostrzeżenie - zacznij się zachowywać

http://pyopengl.sourceforge.net/documentation/manual/gluLookAt.3G.html - tu masz, zacznij mysleć

Offline Krzysiek K.

  • Redaktor
    • DevKK.net

# Lipiec 03, 2007, 18:27:01
Cytuj
no ale nie napisałeś co masz dane. troche to pytanie dziwne bo jak piszesz obsługę kamery to prawdopodobnie będziesz musiał samodzielnie określać wektor UP. ja tak robie korzystając z gluLookAt().
Up upowi nierówny. W gluLookAt podajesz przybliżony wektor "w górę", podczas gdy do wyznaczenia bryły frustum potrzebny jest prawdziwy wektor, czyli taki, który pochyla się razem z kamerą. :)

Cytuj
Krzysiek K. dobra odpowiedz, musze tylko pomyslec - watpie ze cos z tego wyjdzie bo te 16 pozycji jest za bardzo smiesznych :S
Wiem, te nieszczęsne "tabelki". ;) Macierz sama w sobie jest prostą siatka liczb 4x4 w tym przypadku, więc wektory mogą być albo w kolumnach, albo w wierszach (w zalezności od przyjętej notacji). Macierz widoku składa się z trzech wektorów wyznaczających osi kamery postaci [x y z 0] oraz wektora określającego przesunięcie sceny względem kamery postaci [x y z 1]. Pierwsze trzy wiersze (lub kolumny, w zależności od notacji) będą Twoimi wektorami. Pozostaje kwestia dopasowania który jest który (odpowiadają one osiom X Y Z na ekranie) oraz ewentualnej zamiany znaku (w przypadku OpenGL oś Z biegnie do tyłu kamery). :)

Offline ziomber

  • Użytkownik

  • Zbanowany
# Lipiec 03, 2007, 18:47:31
z nudow daje fajnego skrina :S teraz trzeba to analizowac :/

.

  • Gość
# Lipiec 03, 2007, 19:59:08
Z macierzy do wektora.
http://www.facstaff.bucknell.edu/mastascu/eLessonsHTML/Circuit/MatVecMultiply.htm
ta animacja...

Nie możesz podawać do OGL-a własnej pozycji oraz wektora kierunku?
Edit: Dopiero skumałem że ten dziwny pomysł ci Krzysiek zaproponował.
« Ostatnia zmiana: Lipiec 03, 2007, 20:15:08 wysłana przez RageX »

Offline Charibo

  • Redaktor

# Lipiec 03, 2007, 22:22:28
Nie czytalem calego watku, ale czy nie wystarczy poprostu obliczyc iloczynu wektorowego wektorow d i right?

Offline ziomber

  • Użytkownik

  • Zbanowany
# Lipiec 03, 2007, 23:39:37
jak right wylicza sie z d i UP, a ja chce up wyliczyc

Offline novo

  • Użytkownik
    • my devblog

# Lipiec 04, 2007, 01:03:41
Jezeli wykluczysz przypadek w ktorym postac patrzy idealnie w dol(jak np w wiekszosci fpp) to mozesz sobie zalozyc wektor UP jako 0,1,0(pod warunkiem ze na twojej scenie os Y idzie w gore). Potem iloczynem wektorowym wyznaczasz sobie wektor RIGHT. Majac RIGHT i DIR mozesz uzyc ponownie iloczynu wektorowego do wyznacznenia juz poprawnej osi up. Problem bedzie tylko wtedy gdy DIR=(0,-1,0) bo wtedy nasz UP(0,1,0) i DIR tworza prosta i nie da rady bo dostaniesz wektor (0,0,0).

Pozdr.
novo.

Offline ziomber

  • Użytkownik

  • Zbanowany
# Lipiec 04, 2007, 01:14:18
Znalazłem na internecie gotowa klase: metoda krzyśka K tylko że nie do konca

unit FrustumClass;

interface

Uses opengl;

  type
    FrustumArray = Array[0..5, 0..3] of glFloat;

    TFrustum = Object
    private
      Frustum : FrustumArray;
    public
      procedure CalculateFrustum;
      function PointInFrustum(X, Y, Z : glFloat) : Boolean;
      function SphereInFrustum(X, Y, Z, Radius : glFloat) : Boolean;
      function CubeInFrustum(X, Y, Z, Size : glFloat) : Boolean;
      function BoxInFrustum(X, Y, Z, sizeX, sizeY, sizeZ : glFloat) : Boolean;
    end;

implementation

const
  RIGHT   = 0;            // The RIGHT  side of the frustum
  LEFT    = 1;            // The LEFT   side of the frustum
  BOTTOM  = 2;            // The BOTTOM side of the frustum
  TOP     = 3;            // The TOP    side of the frustum
  BACK    = 4;            // The BACK   side of the frustum
  FRONT   = 5;            // The FRONT  side of the frustum


{------------------------------------------------------------------}
{--- This normalizes a plane (A side) from a given frustum.     ---}
{------------------------------------------------------------------}
procedure NormalizePlane(var frustum : FrustumArray; side : Integer);
var magnitude : glFloat;
begin
  magnitude := sqrt(frustum[side][0] * frustum[side][0] +
                    frustum[side][1] * frustum[side][1] +
                    frustum[side][2] * frustum[side][2]);
  frustum[side][0] := frustum[side][0] / magnitude;
  frustum[side][1] := frustum[side][1] / magnitude;
  frustum[side][2] := frustum[side][2] / magnitude;
  frustum[side][3] := frustum[side][3] / magnitude;
end;


{ TFrustum }
         
{---------------------------------------------------------------------}
{---------------------------------------------------------------------}
procedure TFrustum.CalculateFrustum;
var proj, modl, clip : Array[0..15] of glFloat;
begin
  // glGetFloatv() is used to extract information about our OpenGL world.
  // Below, we pass in GL_PROJECTION_MATRIX to abstract our projection matrix.
  glGetFloatv(GL_PROJECTION_MATRIX, @proj);

  // By passing in GL_MODELVIEW_MATRIX, we can abstract our model view matrix.
  glGetFloatv(GL_MODELVIEW_MATRIX, @modl);

  // Now that we have our modelview and projection matrix, if we combine these 2 matrices,
  // it will give us our clipping planes.  To combine 2 matrices, we multiply them.
  clip[ 0] := modl[ 0] * proj[ 0] + modl[ 1] * proj[ 4] + modl[ 2] * proj[ 8] + modl[ 3] * proj[12];
  clip[ 1] := modl[ 0] * proj[ 1] + modl[ 1] * proj[ 5] + modl[ 2] * proj[ 9] + modl[ 3] * proj[13];
  clip[ 2] := modl[ 0] * proj[ 2] + modl[ 1] * proj[ 6] + modl[ 2] * proj[10] + modl[ 3] * proj[14];
  clip[ 3] := modl[ 0] * proj[ 3] + modl[ 1] * proj[ 7] + modl[ 2] * proj[11] + modl[ 3] * proj[15];

  clip[ 4] := modl[ 4] * proj[ 0] + modl[ 5] * proj[ 4] + modl[ 6] * proj[ 8] + modl[ 7] * proj[12];
  clip[ 5] := modl[ 4] * proj[ 1] + modl[ 5] * proj[ 5] + modl[ 6] * proj[ 9] + modl[ 7] * proj[13];
  clip[ 6] := modl[ 4] * proj[ 2] + modl[ 5] * proj[ 6] + modl[ 6] * proj[10] + modl[ 7] * proj[14];
  clip[ 7] := modl[ 4] * proj[ 3] + modl[ 5] * proj[ 7] + modl[ 6] * proj[11] + modl[ 7] * proj[15];

  clip[ 8] := modl[ 8] * proj[ 0] + modl[ 9] * proj[ 4] + modl[10] * proj[ 8] + modl[11] * proj[12];
  clip[ 9] := modl[ 8] * proj[ 1] + modl[ 9] * proj[ 5] + modl[10] * proj[ 9] + modl[11] * proj[13];
  clip[10] := modl[ 8] * proj[ 2] + modl[ 9] * proj[ 6] + modl[10] * proj[10] + modl[11] * proj[14];
  clip[11] := modl[ 8] * proj[ 3] + modl[ 9] * proj[ 7] + modl[10] * proj[11] + modl[11] * proj[15];

  clip[12] := modl[12] * proj[ 0] + modl[13] * proj[ 4] + modl[14] * proj[ 8] + modl[15] * proj[12];
  clip[13] := modl[12] * proj[ 1] + modl[13] * proj[ 5] + modl[14] * proj[ 9] + modl[15] * proj[13];
  clip[14] := modl[12] * proj[ 2] + modl[13] * proj[ 6] + modl[14] * proj[10] + modl[15] * proj[14];
  clip[15] := modl[12] * proj[ 3] + modl[13] * proj[ 7] + modl[14] * proj[11] + modl[15] * proj[15];

  // Now we actually want to get the sides of the frustum.  To do this we take
  // the clipping planes we received above and extract the sides from them.

  // This will extract the RIGHT side of the frustum
  Frustum[RIGHT][0] := clip[ 3] - clip[ 0];
  Frustum[RIGHT][1] := clip[ 7] - clip[ 4];
  Frustum[RIGHT][2] := clip[11] - clip[ 8];
  Frustum[RIGHT][3] := clip[15] - clip[12];

  // Now that we have a normal (A,B,C) and a distance (D) to the plane,
  // we want to normalize that normal and distance.
  NormalizePlane(Frustum, RIGHT);

  // This will extract the LEFT side of the frustum
  Frustum[LEFT][0] := clip[ 3] + clip[ 0];
  Frustum[LEFT][1] := clip[ 7] + clip[ 4];
  Frustum[LEFT][2] := clip[11] + clip[ 8];
  Frustum[LEFT][3] := clip[15] + clip[12];

  // Normalize the LEFT side
  NormalizePlane(Frustum, LEFT);

  // This will extract the BOTTOM side of the frustum
  Frustum[BOTTOM][0] := clip[ 3] + clip[ 1];
  Frustum[BOTTOM][1] := clip[ 7] + clip[ 5];
  Frustum[BOTTOM][2] := clip[11] + clip[ 9];
  Frustum[BOTTOM][3] := clip[15] + clip[13];

  // Normalize the BOTTOM side
  NormalizePlane(Frustum, BOTTOM);

  // This will extract the TOP side of the frustum
  Frustum[TOP][0] := clip[ 3] - clip[ 1];
  Frustum[TOP][1] := clip[ 7] - clip[ 5];
  Frustum[TOP][2] := clip[11] - clip[ 9];
  Frustum[TOP][3] := clip[15] - clip[13];

  // Normalize the TOP side
  NormalizePlane(Frustum, TOP);

  // This will extract the BACK side of the frustum
  Frustum[BACK][0] := clip[ 3] - clip[ 2];
  Frustum[BACK][1] := clip[ 7] - clip[ 6];
  Frustum[BACK][2] := clip[11] - clip[10];
  Frustum[BACK][3] := clip[15] - clip[14];

  // Normalize the BACK side
  NormalizePlane(Frustum, BACK);

  // This will extract the FRONT side of the frustum
  Frustum[FRONT][0] := clip[ 3] + clip[ 2];
  Frustum[FRONT][1] := clip[ 7] + clip[ 6];
  Frustum[FRONT][2] := clip[11] + clip[10];
  Frustum[FRONT][3] := clip[15] + clip[14];

  // Normalize the FRONT side
  NormalizePlane(Frustum, FRONT);
end;


{----------------------------------------------------------------}
{--- This determines if a point is inside of the view frustum ---}
{----------------------------------------------------------------}
function TFrustum.PointInFrustum(X, Y, Z: glFloat): Boolean;
var I : Integer;
begin
  result :=FALSE;
  // Go through all the sides of the frustum
  for I :=0 to 5 do
    // Calculate the plane equation and check if the point is behind a side of the frustum
    if Frustum[i][0] * x + Frustum[i][1] * y + Frustum[i][2] * z + Frustum[i][3] <= 0 then
      exit;  // The point was behind a side, so it ISN'T in the frustum

  // The point was inside of the frustum (In front of ALL the sides of the frustum)
  result :=TRUE;
end;


{----------------------------------------------------------------}
{--- This determines if a sphere is inside our view frustum   ---}
{----------------------------------------------------------------}
function TFrustum.SphereInFrustum(X, Y, Z, Radius: glFloat): Boolean;
var I : Integer;
begin
  result :=FALSE;
  for I :=0 to 5 do
    // Calculate the plane equation and check if the point is behind a side of the frustum
    if Frustum[i][0] * x + Frustum[i][1] * y + Frustum[i][2] * z + Frustum[i][3] <= -radius then
      exit;  // The point was behind a side, so it ISN'T in the frustum

  // The point was inside of the frustum (In front of ALL the sides of the frustum)
  result :=TRUE;
end;


{----------------------------------------------------------------}
{--- This determines if a BOX is in or around our view        ---}
{--- frustum by it's min and max points                       ---}
{----------------------------------------------------------------}
function TFrustum.BoxInFrustum(X, Y, Z, sizeX, sizeY, sizeZ: glFloat): Boolean;
var I : Integer;
begin
  result :=FALSE;
  for I :=0 to 5 do
  begin
    if Frustum[i][0] * (x-sizeX) + Frustum[i][1] * (y-sizeY) + Frustum[i][2] * (z-sizeZ) + Frustum[i][3] > 0 then continue;
    if Frustum[i][0] * (x+sizeX) + Frustum[i][1] * (y-sizeY) + Frustum[i][2] * (z-sizeZ) + Frustum[i][3] > 0 then continue;
    if Frustum[i][0] * (x-sizeX) + Frustum[i][1] * (y+sizeY) + Frustum[i][2] * (z-sizeZ) + Frustum[i][3] > 0 then continue;
    if Frustum[i][0] * (x+sizeX) + Frustum[i][1] * (y+sizeY) + Frustum[i][2] * (z-sizeZ) + Frustum[i][3] > 0 then continue;
    if Frustum[i][0] * (x-sizeX) + Frustum[i][1] * (y-sizeY) + Frustum[i][2] * (z+sizeZ) + Frustum[i][3] > 0 then continue;
    if Frustum[i][0] * (x+sizeX) + Frustum[i][1] * (y-sizeY) + Frustum[i][2] * (z+sizeZ) + Frustum[i][3] > 0 then continue;
    if Frustum[i][0] * (x-sizeX) + Frustum[i][1] * (y+sizeY) + Frustum[i][2] * (z+sizeZ) + Frustum[i][3] > 0 then continue;
    if Frustum[i][0] * (x+sizeX) + Frustum[i][1] * (y+sizeY) + Frustum[i][2] * (z+sizeZ) + Frustum[i][3] > 0 then continue;

    // If we get here, it isn't in the frustum
    exit;
  end;

  // Return a true for the box being inside of the frustum
  result :=TRUE;
end;


{----------------------------------------------------------------}
{--- This determines if a cube is in or around our view    ---}
{---    frustum by using it's center and 1/2 it's length      ---}
{----------------------------------------------------------------}
function TFrustum.CubeInFrustum(X, Y, Z, Size: glFloat): Boolean;
var I : Integer;
begin
  result :=FALSE;
  for I :=0 to 5 do
  begin
    if Frustum[i][0] * (x - size) + Frustum[i][1] * (y - size) + Frustum[i][2] * (z - size) + Frustum[i][3] > 0 then
       continue;
    if Frustum[i][0] * (x + size) + Frustum[i][1] * (y - size) + Frustum[i][2] * (z - size) + Frustum[i][3] > 0 then
       continue;
    if Frustum[i][0] * (x - size) + Frustum[i][1] * (y + size) + Frustum[i][2] * (z - size) + Frustum[i][3] > 0 then
       continue;
    if Frustum[i][0] * (x + size) + Frustum[i][1] * (y + size) + Frustum[i][2] * (z - size) + Frustum[i][3] > 0 then
       continue;
    if Frustum[i][0] * (x - size) + Frustum[i][1] * (y - size) + Frustum[i][2] * (z + size) + Frustum[i][3] > 0 then
       continue;
    if Frustum[i][0] * (x + size) + Frustum[i][1] * (y - size) + Frustum[i][2] * (z + size) + Frustum[i][3] > 0 then
       continue;
    if Frustum[i][0] * (x - size) + Frustum[i][1] * (y + size) + Frustum[i][2] * (z + size) + Frustum[i][3] > 0 then
       continue;
    if Frustum[i][0] * (x + size) + Frustum[i][1] * (y + size) + Frustum[i][2] * (z + size) + Frustum[i][3] > 0 then
       continue;

    // If we get here, it isn't in the frustum
    exit;
  end;

  result :=TRUE;
end;


end.

.

  • Gość
# Lipiec 04, 2007, 02:14:09
To już było, przeglądaj czasami forum... Tam jest wszystko opisane...
http://forum.warsztat.gd/index.php/topic,1499.0.html