Brainer Napisano Grudzień 16, 2007 Zgłoś Share Napisano Grudzień 16, 2007 Witam. Ponownie uderzam do was z pytaniem, bo mam parę wątpliwości, a wy z pewnością zdołacie je rozwiać. A więc zamierzam zabrać się za napisanie własnego silnika 3D. Nie ma być to nic skomplikowanego, ale prosty i wydajny framework, dzięki któremu później będę mógł łatwiej tworzyć sobie inne projekty. Moim problemem jest teraz utworzenie wydajnej hierarchii obiektów na scenie. Mam taki kodzik: CODEtype TTransformationType = (ttMove, ttRotate, ttScale); TTransformations = set of TTransformationType; { .: TBaseSceneObject :. } TBaseSceneObject = class(TPersistent) public { Public declarations } procedure LoadFromFile(const FileName: String); virtual; abstract; procedure SaveToFile(const FileName: String); virtual; abstract; procedure LoadFromStream(const S: TStream); virtual; abstract; procedure SaveToStream(S: TStream); virtual; abstract; procedure Think(const AElapsedTime: Integer); virtual; procedure Render(); virtual; end; { .: TSceneObject :. } TSceneObject = class(TBaseSceneObject) private { Private declarations } FDir: TVector4f; FTrans: TTransformations; FScale: TAffineVector; FPos: TAffineVector; FVisible: Boolean; FMatIdx: Integer; procedure SetDir(const Value: TVector4f); procedure SetPos(const Value: TAffineVector); procedure SetScale(const Value: TAffineVector); public { Public declarations } constructor Create(); procedure Assign(Source: TPersistent); override; procedure Render(); override; property Visible: Boolean read FVisible write FVisible; property MaterialIdx: Integer read FMatIdx write FMatIdx; property Transformations: TTransformations read FTrans write FTrans; property Position: TAffineVector read FPos write SetPos; property Direction: TVector4f read FDir write SetDir; property Scale: TAffineVector read FScale write SetScale; end; Te dwie klasy służą mi do reprezentacji pojedynczego obiektu na scenie. I tutaj pojawia się pierwszy mój problem. Chodzi o wykonywanie przekształceń. Używam takiego kodu: procedure TSceneObject.Render; begin if not FVisible then exit; // Transformations if ttMove in FTrans then glTranslatef(FPos[0], FPos[1], FPos[2]); if ttRotate in FTrans then glRotatef(FDir[3], FDir[0], FDir[1], FDir[2]); if ttScale in FTrans then glScalef(FScale[0], FScale[1], FScale[2]); end; Obawiam się jednak, że ten kod nie jest najlepszym rozwiązaniem. Drugim problemem jest stworzenie systemu hierarchii obiektów. Chodzi mi o to, żeby był jeden obiekt-korzeń, a każdy obiekt pochodny mógł mieć nieskończenie wiele obiektów pochodnych. Kojarzycie o co mi biega? Byłbym wdzięczny za wszelkie informacje. Jeżeli coś nie jest jasne odnośnie mojego problemu, proszę dać znać. Z góry dziękuję. .: Brainer :. patrick.nusbaum@gmail.com Link do komentarza Udostępnij na innych stronach More sharing options...
5corpio Napisano Grudzień 16, 2007 Zgłoś Share Napisano Grudzień 16, 2007 Do przekształceń możesz przechowywać macierz przekształceń a potem mnożyć przez nią będziesz w niej przechowywał wszystkie przekształcenia poskładane a dodatkowo osobno w wektorach możesz jeszcze trzymać te przekształcenia pojedynczo. Drugim problemem jest stworzenie systemu hierarchii obiektów. Chodzi mi o to, żeby był jeden obiekt-korzeń, a każdy obiekt pochodny mógł mieć nieskończenie wiele obiektów pochodnych. Kojarzycie o co mi biega?Kojarze ale po co nieskończenie wiele xD ? Zbyt "dalekie" dziedziczenie czy też nadmierne nie jest najlepszym nawykiem. Ale pewne klasy bazowe dla reszty obiektów to wiadomo wyjście dobre. Ot taka mini-strona moja po godzinach http://www.wnetrzekuchni.pl Link do komentarza Udostępnij na innych stronach More sharing options...
Force Napisano Grudzień 16, 2007 Zgłoś Share Napisano Grudzień 16, 2007 Macierze są good. A jeśli chodzi o te listy, to po poprostu niech każdy obiekt ma listę TList dzieci. I w czasie renderowanie już jak się wyrenderuje obiekt wywoływać Render dla dzieci. Baza tysięcy lotnisk: http://airportsbase.com Link do komentarza Udostępnij na innych stronach More sharing options...
Brainer Napisano Grudzień 16, 2007 Autor Zgłoś Share Napisano Grudzień 16, 2007 CYTAT(5corpio @ nie, 16 gru 2007 - 17:39) Do przekształceń możesz przechowywać macierz przekształceń a potem mnożyć przez nią będziesz w niej przechowywał wszystkie przekształcenia poskładane a dodatkowo osobno w wektorach możesz jeszcze trzymać te przekształcenia pojedynczo. Właśnie tak myślałem o tych macierzach, ale nie za bardzo rozumiem, jak to stosować. Chodzi Ci na przykład o coś takiego? procedure TSceneObject.Render; begin if not FVisible then exit; glPushMatrix(); // Transformations if ttMove in FTrans then glTranslatef(FPos[0], FPos[1], FPos[2]); if ttRotate in FTrans then glRotatef(FDir[3], FDir[0], FDir[1], FDir[2]); if ttScale in FTrans then glScalef(FScale[0], FScale[1], FScale[2]); glPopMatrix(); end; A jeśli chodzi o te listy, to po poprostu niech każdy obiekt ma listę TList dzieci. I w czasie renderowanie już jak się wyrenderuje obiekt wywoływać Render dla dzieci. Dobry pomysł! A co myślisz o TThreadList? Czy wpłynie to jakoś na wydajność wykonywanego kodu? .: Brainer :. patrick.nusbaum@gmail.com Link do komentarza Udostępnij na innych stronach More sharing options...
Force Napisano Grudzień 16, 2007 Zgłoś Share Napisano Grudzień 16, 2007 Źle zrozumiałeś 5corpio. Chodzi o to, że masz macierze dla obrotu, skalowania i przesunięcia. I nie musisz po kolej każdą "użyć" (dziwna nazwa:P) to możesz je przez siebie przemnożyć (kolejność ważna) i ją "użyć". Nie wiem po co TThreadList, to nawet nie logiczne, masz mieć listę obiektów Baza tysięcy lotnisk: http://airportsbase.com Link do komentarza Udostępnij na innych stronach More sharing options...
Brainer Napisano Grudzień 16, 2007 Autor Zgłoś Share Napisano Grudzień 16, 2007 CYTAT(Force @ nie, 16 gru 2007 - 20:58) Źle zrozumiałeś 5corpio. Chodzi o to, że masz macierze dla obrotu, skalowania i przesunięcia. I nie musisz po kolej każdą "użyć" (dziwna nazwa:P) to możesz je przez siebie przemnożyć (kolejność ważna) i ją "użyć". Czyli chodzi o coś takiego? public { Public declarations } // ... property TransformationMatrix: TMatrix read FTransMat write FTransMat; property RotationMatrix: TMatrix read FRotMat write FRotMat; property ScaleMatrix: TMatrix read FScaleMat write FScaleMat; I jak potem "używać" tych macierzy? Nie wiem po co TThreadList, to nawet nie logiczne, masz mieć listę obiektów No przecież wspomniałeś, żeby każdy obiekt miał listę TList dzieci. Zatem, czy można to zastąpić TThreadList i czy zyskam jakiś wzrost wydajności? .: Brainer :. patrick.nusbaum@gmail.com Link do komentarza Udostępnij na innych stronach More sharing options...
5corpio Napisano Grudzień 16, 2007 Zgłoś Share Napisano Grudzień 16, 2007 http://www.cs.rutgers.edu/~decarlo/428/gl_...multmatrix.html i ten: http://www.cosc.brocku.ca/Offerings/3P98/c...s/2d_3d_xforms/ w tym drugim masz pokazane, które elementy macierzy odpowiadają za jakie przekształcenia. Chociaż używanie zwykłego glRotate etc. sprowadza się do tego samego co masz przy używaniu macierzy ale wykonywane to jest już nie "przez Ciebie" więc wsumie możesz pozostawić swoje rozwiązanie, które poniekąd też jest dobre. Edit: A jednak nie zrozumiałem chyba twojego drugiego pytania po co Ci obiekt "mega" nadrzędny, który w liście ma ileś tam dzieci, które powiedzmy "latają" po scenie? Nie lepiej zrobić liste obiektów do siebie ew. dolinkowanych, które jakoś tam na siebie wpływają ? Ot taka mini-strona moja po godzinach http://www.wnetrzekuchni.pl Link do komentarza Udostępnij na innych stronach More sharing options...
Brainer Napisano Grudzień 16, 2007 Autor Zgłoś Share Napisano Grudzień 16, 2007 http://www.cs.rutgers.edu/~decarlo/428/gl_...multmatrix.html Mhm. Force wspomniał coś jeszcze o kolejności mnożenia macierzy. O co chodzi? EDIT No chcę zrobić tak, jak to jest w GLScene. Tam jest jeden obiekt nadrzędny, a reszta jest obiektami-dziećmi. .: Brainer :. patrick.nusbaum@gmail.com Link do komentarza Udostępnij na innych stronach More sharing options...
5corpio Napisano Grudzień 16, 2007 Zgłoś Share Napisano Grudzień 16, 2007 Chodzi o to, że kolejność składania przekształceń w innej kolejności może dać inny wynik niż złożenei tych samych przekształceń w odwrotnej. Obrót->przesunięcie nie będzie tak samo jako przesunięcie->obrót etc. No chcę zrobić tak, jak to jest w GLScene. Tam jest jeden obiekt nadrzędny, a reszta jest obiektami-dziećmi.Hmm a co to daje bo szczerze powiedziawszy nie wiem ? To zależy co potrzebujesz uzyskać i co chcesz mieć ? Ot taka mini-strona moja po godzinach http://www.wnetrzekuchni.pl Link do komentarza Udostępnij na innych stronach More sharing options...
Brainer Napisano Grudzień 16, 2007 Autor Zgłoś Share Napisano Grudzień 16, 2007 Chodzi o to, że kolejność składania przekształceń w innej kolejności może dać inny wynik niż złożenei tych samych przekształceń w odwrotnej. Obrót->przesunięcie nie będzie tak samo jako przesunięcie->obrót etc. Czyli jak mniemam, najpierw ma być przesunięcie, potem obrót, a na koniec skalowanie. Dobrze kminię? EDIT No chcę sobie zrobić drzewo obiektów, gdzie będzie tylko jeden obiekt nadrzędny (scena), a reszta będzie niżej w hierarchii. .: Brainer :. patrick.nusbaum@gmail.com Link do komentarza Udostępnij na innych stronach More sharing options...
Force Napisano Grudzień 16, 2007 Zgłoś Share Napisano Grudzień 16, 2007 Ni o ile pamiętam to pierwszo skalowanie, potem obrót a na końcu przesunięcie. Baza tysięcy lotnisk: http://airportsbase.com Link do komentarza Udostępnij na innych stronach More sharing options...
Blind Napisano Grudzień 16, 2007 Zgłoś Share Napisano Grudzień 16, 2007 Ja mam skalowanie>obrot>przesuniecie i dziala dobrze i raczej jak to pisalem nie przejmowalem sie kolejnoscia(moze po prostu mi sie udalo ) www.blinder.pl - Blog Link do komentarza Udostępnij na innych stronach More sharing options...
Brainer Napisano Grudzień 16, 2007 Autor Zgłoś Share Napisano Grudzień 16, 2007 Ja mam skalowanie>obrot>przesuniecie i dziala dobrze i raczej jak to pisalem nie przejmowalem sie kolejnoscia(moze po prostu mi sie udalo ) Okej, czyli tak to zrobię. Teraz mam małą prośbę. Mógłbym mi ktoś pokazać, jak się używa tej funkcji glMultMatrix? Będę bardzo, bardzo wdzięczny... .: Brainer :. patrick.nusbaum@gmail.com Link do komentarza Udostępnij na innych stronach More sharing options...
Blind Napisano Grudzień 16, 2007 Zgłoś Share Napisano Grudzień 16, 2007 Pokazac? spytaj google, a jak bedziesz mial jakies watpliwosci to zadaj konkretne pytanie. www.blinder.pl - Blog Link do komentarza Udostępnij na innych stronach More sharing options...
5corpio Napisano Grudzień 16, 2007 Zgłoś Share Napisano Grudzień 16, 2007 Ta funkcja mnoży aktualnie używaną macierz (GL_MODELVIEW_MATRIX, GL_PROJECTION_MATRIX albo GL_TEXTURE_MATRIX) przez macierz, którą przekażesz jako parametr tej funkcji i tyle. A jak wiadomo aktualnie używaną macierz ustawia się w ogl-u przez: glMatrixMode xD Ot taka mini-strona moja po godzinach http://www.wnetrzekuchni.pl Link do komentarza Udostępnij na innych stronach More sharing options...
Brainer Napisano Grudzień 16, 2007 Autor Zgłoś Share Napisano Grudzień 16, 2007 Ta funkcja mnoży aktualnie używaną macierz (GL_MODELVIEW_MATRIX, GL_PROJECTION_MATRIX albo GL_TEXTURE_MATRIX) przez macierz, którą przekażesz jako parametr tej funkcji i tyle. A jak wiadomo aktualnie używaną macierz ustawia się w ogl-u przez: glMatrixMode xD Aha! Czyli teraz pozostało tylko wyliczyć macierz skalowania, obrotu i przesunięcia i użyć ich z tą funkcją, tak? .: Brainer :. patrick.nusbaum@gmail.com Link do komentarza Udostępnij na innych stronach More sharing options...
Spider100 Napisano Grudzień 17, 2007 Zgłoś Share Napisano Grudzień 17, 2007 5corpio Hmm a co to daje bo szczerze powiedziawszy nie wiem ? To zależy co potrzebujesz uzyskać i co chcesz mieć ? Takie podejście ma wiele zalet jest bardzo przydatne w pisaniu animacji kości (odwrotna kinematyka), do ustawienia pozycji względnej obieku np efektor systemu cząsteczek zawsze przyczepiony w danym punkcie obiektu... Co do rotacji warto też używać kwaternionów nie tylko macierzy w tym przypadku jeśli na hierarchii byśmy chcieli robić interpolacje to macierze mogą nam przysporzyć sporo kłopotów... Jeśli chodzi o mnożenie kolejnych macierzy obiektu i ich kolejność to odpowiem lepiej niż poprzednicy wcale nie trzeba ich mnożyć przed wysłaniem do OpenGL tu jest pewna optymalizacja zamiast mnożyć macierze możemy je normalnie uzupełniać. Macierz do wysłania openglowi wygląda mniej więcej tak bez skalowania: X.x X.y X.z 0 Y.x Y.y Y.z 0 Z.x Z.y Z.z 0 T.x T.y T.z 1 X, Y, Z - obrót na osiach (baza przestrzeni tzw. Trójścian Freneta) T Przesuniecie (przesunięcie bazy) Jest jeszcze skalowanie które znajduje się na przekątnej tej macierzy jest rzadko zrywane więc można je pomnożyć w szczególnych przypacdkach. Przy okazji przypominam by zwrócić uwagę na to czy układ jest lewo czy prawoskrętny bo mnożenie macierzy może źle działać. Dla ciekawostki dodam ze jak byśmy chcieli użyć przekształcenia odwrotnego wystarczy że zrobimy transpozycje macierzy obrotu i przeciwność wektora przesunięcia. jest to spore uproszczenie bo liczenie odwrotności macierzy 4x4 to niezły hard core Pozdrawiam i życzę powodzenia w pisaniu hieracrchi. www.spider.dathox.com Link do komentarza Udostępnij na innych stronach More sharing options...
Brainer Napisano Grudzień 30, 2007 Autor Zgłoś Share Napisano Grudzień 30, 2007 Hej. Sorry za odgrzebywanie tego tematu, ale nie chcę zakładać nowego. Otóż doszedłem do czegoś takiego: CODEunit UBEObjects; interface uses Classes, // -- Headers -- dglOpenGL, // -- Base Units -- VectorGeometry, VectorTypes; type { .: TBaseObject :. } TBaseObject = class(TObject) public { Public declarations } procedure LoadFromStream(const S: TStream); virtual; abstract; procedure LoadFromFile(const FileName: String); virtual; abstract; procedure SaveToStream(S: TStream); virtual; abstract; procedure SaveToFile(const FileName: String); virtual; abstract; end; { .: TSceneObject :. } TSceneObject = class(TBaseObject) private { Private declarations } FPos: TAffineVector; FRot: TVector4f; FScale: TAffineVector; procedure SetPos(const Value: TAffineVector); procedure SetRot(const Value: TVector4f); procedure SetScale(const Value: TAffineVector); public { Public declarations } Children: TList; constructor Create(); destructor Destroy(); override; procedure TransformationChanged(); procedure Render(); virtual; abstract; procedure Think(const ElapsedTime: Integer); virtual; abstract; property Position: TAffineVector read FPos write SetPos; property Rotation: TVector4f read FRot write SetRot; property Scale: TAffineVector read FScale write SetScale; end; { .: TCube :. } TCube = class(TSceneObject) public { Public declarations } procedure Render(); override; end; implementation { TSceneObject } constructor TSceneObject.Create; begin inherited Create(); Children := TList.Create(); FPos := AffineVectorMake(0.0, 0.0, 0.0); FRot := VectorMake(0.0, 1.0, 0.0, 0.0); FScale := AffineVectorMake(1.0, 1.0, 1.0); end; destructor TSceneObject.Destroy; begin Children.Free(); inherited Destroy(); end; procedure TSceneObject.SetPos(const Value: TAffineVector); begin FPos := Value; end; procedure TSceneObject.SetRot(const Value: TVector4f); begin FRot := Value; end; procedure TSceneObject.SetScale(const Value: TAffineVector); begin FScale := Value; end; procedure TSceneObject.TransformationChanged; var RotM, TransM, ScaleM: TMatrix; begin ScaleM := CreateScaleMatrix(FScale); TransM := CreateTranslationMatrix(FPos); RotM := CreateRotationMatrix(FRot, FRot[3]); glMultMatrixf(@TransM); glMultMatrixf(@RotM); glMultMatrixf(@ScaleM); end; { TCube } procedure TCube.Render; var I: Integer; begin glPushMatrix(); TransformationChanged(); glBegin(GL_QUADS); // Front Face glNormal3f(0.0, 0.0, 1.0); glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, 1.0); glTexCoord2f(1.0, 0.0); glVertex3f(1.0, -1.0, 1.0); glTexCoord2f(1.0, 1.0); glVertex3f(1.0, 1.0, 1.0); glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, 1.0); // Back Face glNormal3f(0.0, 0.0, -1.0); glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, -1.0); glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, 1.0, -1.0); glTexCoord2f(0.0, 1.0); glVertex3f(1.0, 1.0, -1.0); glTexCoord2f(0.0, 0.0); glVertex3f(1.0, -1.0, -1.0); // Top Face glNormal3f(0.0, 1.0, 0.0); glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, -1.0); glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, 1.0, 1.0); glTexCoord2f(1.0, 0.0); glVertex3f(1.0, 1.0, 1.0); glTexCoord2f(1.0, 1.0); glVertex3f(1.0, 1.0, -1.0); // Bottom Face glNormal3f(0.0, -1.0, 0.0); glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, -1.0, -1.0); glTexCoord2f(0.0, 1.0); glVertex3f(1.0, -1.0, -1.0); glTexCoord2f(0.0, 0.0); glVertex3f(1.0, -1.0, 1.0); glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, 1.0); // Right Face glNormal3f(1.0, 0.0, 0.0); glTexCoord2f(1.0, 0.0); glVertex3f(1.0, -1.0, -1.0); glTexCoord2f(1.0, 1.0); glVertex3f(1.0, 1.0, -1.0); glTexCoord2f(0.0, 1.0); glVertex3f(1.0, 1.0, 1.0); glTexCoord2f(0.0, 0.0); glVertex3f(1.0, -1.0, 1.0); // Left Face glNormal3f(-1.0, 0.0, 0.0); glTexCoord2f(0.0, 0.0); glVertex3f(-1.0, -1.0, -1.0); glTexCoord2f(1.0, 0.0); glVertex3f(-1.0, -1.0, 1.0); glTexCoord2f(1.0, 1.0); glVertex3f(-1.0, 1.0, 1.0); glTexCoord2f(0.0, 1.0); glVertex3f(-1.0, 1.0, -1.0); glEnd(); for I := 0 to Children.Count -1 do TSceneObject(Children).Render(); glPopMatrix(); end; end. Jednak dalej nie spełnia to zadania. Znaczy, transformacje działają elegancko dla obiektu nadrzędnego, ale gdy renderuję obiekty z listy Children, to działają źle (dla potomków). Nie implementowałem jeszcze żadnej hierarchii, ale zrobiłem tak, jak mi doradził Force z użyciem obiektu TList. Co mam zrobić, żeby to działało? Albo inne pytanie: co robię źle? Z góry dziękuję za wszelką pomoc. .: Brainer :. patrick.nusbaum@gmail.com Link do komentarza Udostępnij na innych stronach More sharing options...
Force Napisano Grudzień 30, 2007 Zgłoś Share Napisano Grudzień 30, 2007 Źle czyli co się dzieje? Mi się wydaje, że TransformationChanged masz zepsute, znaczy nie podoba mi się ta funkcja, Bo pieewszo powinieneś ustawić macierz na jednostkową, a potem przez nią przemnażać. Baza tysięcy lotnisk: http://airportsbase.com Link do komentarza Udostępnij na innych stronach More sharing options...
Brainer Napisano Grudzień 30, 2007 Autor Zgłoś Share Napisano Grudzień 30, 2007 Źle czyli co się dzieje? Mi się wydaje, że TransformationChanged masz zepsute, znaczy nie podoba mi się ta funkcja, Bo pieewszo powinieneś ustawić macierz na jednostkową, a potem przez nią przemnażać. Tutaj jest link do EXEka: http://www.sendspace.com/file/htf6ag A gdy próbuję najpierw ustawić macierz na jednostkową, a dopiero w niej grzebać, to drugi sześcian się nie rusza. .: Brainer :. patrick.nusbaum@gmail.com Link do komentarza Udostępnij na innych stronach More sharing options...
5corpio Napisano Grudzień 30, 2007 Zgłoś Share Napisano Grudzień 30, 2007 Hmm nie chce mi się tego całego lookać ale w metodzie render: glPopMatrix() Wrzuć przed pętle renderującą dzieci ale też nie wiem czy to pomoże bo to zależy ;p Ot taka mini-strona moja po godzinach http://www.wnetrzekuchni.pl Link do komentarza Udostępnij na innych stronach More sharing options...
Force Napisano Grudzień 30, 2007 Zgłoś Share Napisano Grudzień 30, 2007 wg nie pop jest dobrze ustawione. uważam, że tak jak mas pętle to rób tak dla iteracji begin glPushMatrix Renderuj dziecko glPopMatrix end; Baza tysięcy lotnisk: http://airportsbase.com Link do komentarza Udostępnij na innych stronach More sharing options...
5corpio Napisano Grudzień 30, 2007 Zgłoś Share Napisano Grudzień 30, 2007 Mogę się mylić ale wg. mnie jest jednak źle bo on ma chyba tak, że dzieci mają swoje przekształcenia nie względem "rodzica" tylko hmm "względem świata" ciężko mi się wyrazić a jak odłoży na stos macierz zrobi przekształcenia rodzica jeszcze jej nie zdejmie i znów wykona przekształcenia dziecka to zostaną one wykonane przecież już względem tego nowego układu rodzica dlatego efekty są inne od oczekiwanych tak ? Ot taka mini-strona moja po godzinach http://www.wnetrzekuchni.pl Link do komentarza Udostępnij na innych stronach More sharing options...
Spider100 Napisano Grudzień 30, 2007 Zgłoś Share Napisano Grudzień 30, 2007 Możecie mi wytłumaczyć o w tym exe jest źle bo chyba nie zauważyłem jak dla mnie to dobrze działa heh www.spider.dathox.com Link do komentarza Udostępnij na innych stronach More sharing options...
5corpio Napisano Grudzień 30, 2007 Zgłoś Share Napisano Grudzień 30, 2007 No chyba kaman, że ten drugi krąży wokół tego pierwszego a powinien sam się obracać w miejscu ale to mój domysł Ot taka mini-strona moja po godzinach http://www.wnetrzekuchni.pl Link do komentarza Udostępnij na innych stronach More sharing options...
Polecane posty
Zarchiwizowany
Ten temat jest archiwizowany i nie można dodawać nowych odpowiedzi.