Mausbewegungen umrechnen
Übersicht

![]() |
derAtomkeksehemals "Sethus"Betreff: Mausbewegungen umrechnen |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hallo zusammen,
ich würde meinen Worldeditor gerne etwas benutzerfreundlicher gestalten: Dafür sollen Verschiebungen sowohl von Texturen als auch von Meshes per Maus präzise gesteuert werden können. Dafür soll natürlich die Perspektive der Kamera berücksichtigt werden. Wenn ein von der Kamera sehr weit entferntes Objekt zur Seite bewegt werden soll, muss es natürlich stärker bewegt werden, als ein sich direkt vor der Kamera befindliches Objekt. Bei Texturen und Rotation von Objekten wirds noch schwieriger: Hier muss ja nicht nur die Distanz, sondern auch die Neigung der gepickten Oberfläche zur Kamera, sowie deren Rotation berücksichtigt werden. Ich will also quasi den einen Punkt, den ich mit der Maus greife, festhalten und (auf einer vorher im Editor festgelegten Achse) verschieben / drehen können. Ich habe schon einiges ausprobiert mit den blitzinternen Koordinatentransformations-Funktionen, bin dabei aber noch nicht auf den grünen Zweig gekommen. Ich hoffe ich habe das Problem verständlich genug formuliert und ihr könnt mir helfen! ![]() |
||
![]() |
Jan_Ehemaliger Admin |
![]() Antworten mit Zitat ![]() |
---|---|---|
BlitzBasic: [AUSKLAPPEN] CameraPick() Daraus bekommst du die 3D Verschiebung der Maus, wenn du das über 2Sachen machst. Rotation sollte ja egal sein, weil die ja entfernungsunabhängig ist. kleiner Tip noch: 3D Pytagoras: Code: [AUSKLAPPEN] entfernung#=sqr((xneu-xalt)^2+(yneu-yalt)^2+(zneu-zalt)^2)
Lg. Jan_ |
||
between angels and insects |
![]() |
Midimaster |
![]() Antworten mit Zitat ![]() |
---|---|---|
naja....
Wenn du mit dem CameraPick() arbeitest, erhältst du ja drei wichtige Angaben: PickedEntity() damit weißt du welches Objekt du anvisierst hast. Da du dich ja entschieden hast, die gültige Achse vorher festzulegen, musst Du das Entity jetzt nur nur im Bezug der World-Koordinaten() bewegen. Dazu wirst Du auswerten müssen wie sich seit dem Pick die Maus bewegt hat. Willst Du drehen, dann wäre es vielleicht klug, statt der World()-Lage des Objektes, in der Fortsetzung gleich mit dem lokalen Koordinatensystem zu arbeiten. So dreht sich das Objekt bei einer y-Drehung um "seine" y-Achse. PickedSurface() liefert dir gleich mal die Oberfläche, die auf dem Entity vom Pick getroffen wurde. Um nun die Texturen zu verschieben, würde ich gar nicht die World() umrechnen, sondern in der Fortsetzung gleich nur mit dem lokalen Koordinatensystem der Surface arbeiten. Da gibt es dann nur U und V (wie X und Y). So würde ich das auch als User erwarten |
||
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe |
![]() |
derAtomkeksehemals "Sethus" |
![]() Antworten mit Zitat ![]() |
---|---|---|
Danke ihr beiden, aber leider ist das alles nichts neues für mich. Das Problem ist, dass ich die Linie der Differenz der 3D-Koordinaten der Maus-Picks in eine 2D-Linie auf der gepickten Surface umwandeln muss, damit die Verschiebung auch bei Rotation des Objektes bzw. anderer Perspektive der Kamera auch passt.
Mittlerweile habe ich durch ausprobieren das Ganze für einen 1x1x1 großen Cube hinbekommen. Hier mal mein Code soweit dazu (Pfeiltasten - Objekt drehen, Mausklick - Surface auswählen, Maus bewegen - Textur auf Surface verschieben ; Textur müsstet ihr noch ersetzen): Code: [AUSKLAPPEN] Graphics3D 640,480,0,2
SetBuffer BackBuffer() camera=CreateCamera() light=CreateLight(1) RotateEntity light,90,0,0 Local brushWhite = CreateBrush(255, 255, 255) Local brushRed = CreateBrush() Local tex = LoadTexture("D:\gras.jpg") BrushTexture brushRed, tex ;cube = CreateCone(12) cube=CSGAddMyMeshCubeX(0, -.5, -.5, -.5, .5, .5, .5, 0, 0, 0, brushWhite, brushWhite, brushWhite, brushWhite, brushWhite, brushWhite) ;CreateCube() ;cube() EntityPickMode cube,2 EntityColor cube,200,200,250 PositionEntity cube,0,0,3 RotateEntity cube,0,0,0 Local iSelectedSurf Local fMovU# Local fMovV# Local fLastX#, fLastY#, fLastZ# Local fCurrX#, fCurrY#, fCurrZ# Local fNormX#, fNormY#, fNormZ# Local fFacX#, fFacY#, fFacZ# While Not KeyDown(1) If KeyDown(200) Then TurnEntity cube, 0.5, 0, 0 If KeyDown(208) Then TurnEntity cube, -0.5, 0, 0 If KeyDown(203) Then TurnEntity cube, 0, 0.5, 0 If KeyDown(205) Then TurnEntity cube, 0, -0.5, 0 RenderWorld If MouseHit(1) Then CameraPick camera, MouseX(), MouseY() iSelectedSurf = PickedSurface() For i=1 To CountSurfaces(cube) If GetSurface(cube,i) <> iSelectedSurf Then PaintSurface GetSurface(cube,i), brushWhite Else PaintSurface iSelectedSurf, brushRed End If Next End If ent = CameraPick(camera, MouseX(), MouseY()) If ent <> 0 Then TFormPoint PickedX#(), PickedY#(), PickedZ#(), 0, cube fCurrX# = TFormedX#() fCurrY# = TFormedY#() fCurrZ# = TFormedZ#() Text 0, 0, "Local dX: " + (fCurrX# - fLastX#) Text 0,15, "Local dY: " + (fCurrY# - fLastY#) Text 0,30, "Local dZ: " + (fCurrZ# - fLastZ#) TFormNormal PickedNX#(), PickedNY#(), PickedNZ#(), 0, ent fNormX# = TFormedX#() fNormY# = TFormedY#() fNormZ# = TFormedZ#() If (fNormX# < 0.01) And (fNormX# > -0.01) Then fNormX# = 0.0 If (fNormY# < 0.01) And (fNormY# > -0.01) Then fNormY# = 0.0 If (fNormZ# < 0.01) And (fNormZ# > -0.01) Then fNormZ# = 0.0 Text 400, 0, "Local picked NX: " + fNormX# Text 400,15, "Local picked NY: " + fNormY# Text 400,30, "Local picked NZ: " + fNormZ# fMovU# = fNormZ# * (fCurrX# - fLastX#) - fNormX# * (fCurrZ# - fLastZ#) + Abs(fNormY#) * (fCurrZ# - fLastZ#) fMovV# = fNormY# * (fCurrX# - fLastX#) + (1-Abs(fNormY#)) * (fCurrY# - fLastY#) fLastX# = fCurrX# fLastY# = fCurrY# fLastZ# = fCurrZ# End If If iSelectedSurf <> 0 Then For i = 0 To CountVertices(iSelectedSurf) - 1 VertexTexCoords iSelectedSurf, i, VertexU#(iSelectedSurf, i) + fMovU#, VertexV#(iSelectedSurf, i) + fMovV# Next End If Flip Wend End Function CSGAddMyMeshCubeX(m,x1#,y1#,z1#,x2#,y2#,z2#,cx,cy,cz,br_top,br_bottom,br_left, br_right,br_front,br_back,o_top=1,o_bottom=1,o_left=1,o_right=1,o_front=1,o_back=1) ;MR 31.10.2002 ;Create a Cube centered ;m =Entity Handle 0=Create a new one :-) ;x1,x2 =From X1 To X2 ;cx,cy,cy=Center ;br_ =Brush Handle ;o_ =Optional 1=Create 0=No Create Local w#,h#,d# ;w#=witdh (X) ;h#=height (Y) ;d#=depth (Z) w#=x2#-x1# h#=y2#-y1# d#=z2#-z1# ;--------------------- Center ? If cx=1 Then x1=x1-w/2.0 x2=x2-w/2.0 EndIf If cy=1 Then y1=y1-h/2.0 y2=y2-h/2.0 EndIf If cz=1 Then z1=z1-d/2.0 z2=z2-d/2.0 EndIf ;----------------------------- If m=0 Then m=CreateMesh() EndIf ;----------------------------- ;top face If o_top=1 Then s=CreateSurface( m , br_top) AddVertex s,x1,y2,z2,0,1:AddVertex s,x2,y2,z2,0,0 AddVertex s,x2,y2,z1,1,0:AddVertex s,x1,y2,z1,1,1 AddTriangle s,0,1,2:AddTriangle s,0,2,3 EndIf ;bottom face If o_bottom=1 Then s=CreateSurface( m , br_bottom) AddVertex s,x1,y1,z1,1,0:AddVertex s,x2,y1,z1,1,1 AddVertex s,x2,y1,z2,0,1:AddVertex s,x1,y1,z2,0,0 AddTriangle s,0,1,2:AddTriangle s,0,2,3 EndIf ;left face If o_left=1 Then s=CreateSurface( m , br_left) AddVertex s,x1,y2,z2,0,0:AddVertex s,x1,y2,z1,1,0 AddVertex s,x1,y1,z1,1,1:AddVertex s,x1,y1,z2,0,1 AddTriangle s,0,1,2:AddTriangle s,0,2,3 EndIf ;right face If o_right=1 Then s=CreateSurface( m , br_right) AddVertex s,x2,y2,z1,0,0:AddVertex s,x2,y2,z2,1,0 AddVertex s,x2,y1,z2,1,1:AddVertex s,x2,y1,z1,0,1 AddTriangle s,0,1,2:AddTriangle s,0,2,3 EndIf ;front face If o_front=1 Then s=CreateSurface( m , br_front) AddVertex s,x1,y2,z1,0,0:AddVertex s,x2,y2,z1,1,0 AddVertex s,x2,y1,z1,1,1:AddVertex s,x1,y1,z1,0,1 AddTriangle s,0,1,2:AddTriangle s,0,2,3 EndIf ;back face If o_back=1 Then s=CreateSurface( m , br_back) AddVertex s,x2,y2,z2,0,0:AddVertex s,x1,y2,z2,1,0 AddVertex s,x1,y1,z2,1,1:AddVertex s,x2,y1,z2,0,1 AddTriangle s,0,1,2:AddTriangle s,0,2,3 EndIf UpdateNormals m ;EntityPickMode m,2 ;Poly Return m End Function Das Problem dabei ist, dass das Ganze nur für1x1x1 große Cubes funktioniert. Auf einer Kugel gehts auch noch... Aber auf einem Kegel funktioniert die Unterseite beispielsweise nicht wirklich. Und sobald ich das Ganze auf Oberflächen von durch CSG entstandene Objekte anwende, funktioniert schon mal garnichts mehr. Das muss doch irgendwie möglich sein, aus den Normalen-Koordinaten und den lokalen gepickten Koordinaten irgendwie 2D-Surface-Koordinaten zu basteln..?? Edit: Und die Größe der Surface muss ich auch noch irgendwie einfließen lassen, sonst passt die Bewegungsgeschwindigkeit wieder nicht mit der der Maus überein ![]() |
||
![]() |
Mr.Keks |
![]() Antworten mit Zitat ![]() |
---|---|---|
Hi Sethus, die Normalen von Vertices/Triangles haben im allgemeinen nicht zwingend etwas mit den UV-Koordinaten zu tun, um die es dir hier ja eigentlich geht. Die UV-Verzerrung richtig umzusetzen, ist vermutlich seehr unangenehm - bin da allerdings auch planlos.
Ich würde dir folgendes Verfahren mit einer linearen Abbildung vorschlagen, das für gewöhnlich eine gute Näherung darstellen sollte: Schau, welches Dreieck gepickt wurde. Hol dir die Vertexkoordinaten und wandle sie in Weltkoordinaten um, hol dir die entsprechenden Bildschirmkoordinaten mit CameraProject ![]() |
||
MrKeks.net |
![]() |
Midimaster |
![]() Antworten mit Zitat ![]() |
---|---|---|
also ich bin noch nicht ganz davon überzeugt, dass mein weg nicht vielleicht doch eine Lösung für dich wäre...
hier mal ein Ansatz. die Surface wird mit der Maus bewegt. eine Bewegung in MouseX-Achse bewegt auch die Surface in "ihrer" X-Achse. Es kommt völlig ohne die Berechnungen aus: BlitzBasic: [AUSKLAPPEN] While Not KeyDown(1) Hier wäre nur noch die Frage zu klären, wie man herausfindet, ob die Surface-Achsen der Surface einigermaßen mit der Maus übereinstimmen. Dann noch eine Anregung: wird die Maus auf dem Mesh bewegt ergeben sich doch sofort andere PickedX(),... Koordinaten. Man könnte doch durch Subtrahieren aus den vorherigen PickedX() und dem neuen eine Art Vektor errechnen, der dann zeigt, wie die Bewegung auf dem Mesh ausgesehen hat? |
||
Gewinner des BCC #53 mit "Gitarrist vs Fussballer" http://www.midimaster.de/downl...ssball.exe |
![]() |
derAtomkeksehemals "Sethus" |
![]() Antworten mit Zitat ![]() |
---|---|---|
@Midimaster: Die Differenz der gepickten Koordinaten bilden ist das, was ich getan habe ![]() ![]() @Mr. Keks: Damit sollte ich das Problem mit der Skalierung in den Griff bekommen. Die Normale muss ich doch aber irgendwie einbinden, um auf die Neigung der Fläche (also nicht durch Rotation, sondern beispielsweise die Schrägen Seiten eines Kegels) einzugehen. Wenn ich flach vor eine zur Kamera parallele Fläche gucke, dann entspricht die V-Bewegung der Y-Bewegung der Maus. Wenn die Fläche nach hinten geneigt ist (die Normale also nicht 0, 0, -1; sondern zB. 0, 0.5, -1), dann muss sich die Textur in V-Richtung schneller bewegen. (-> Pythagoras und so.). Oder habe ich das bei dir jetzt nur überlesen?` Das wird aber doch alles irgendwie komplexer (und bei gewölbten Flächen u.a. auch ungenauer), als ich mir das gedacht hatte. Wahrscheinlich ist es besser, wenn ich einfach ein Fenster zum Editor hinzufüge, in dem die auf der Surface befindliche Textur angezeigt wird und dort per Maus verschoben werden kann. Ist ja jetzt auch nicht so schlimm, wäre halt ein nettes Feature gewesen ![]() Edit: Nachdem ich die UV-Koordinaten bei der Cube-Erstellung angepasst habe, funktioniert das Ganze jetzt auch ohne komische Umrechnungen. Brauche ich also nur noch Algos zur Erstellung von Kugeln, Zylindern, Kegeln, ... ![]() |
||
![]() |
Noobody |
![]() Antworten mit Zitat ![]() |
---|---|---|
Die Problemlösung sieht eigentlich so aus: Man macht einen CameraPick![]() ![]() Das Problem ist aber, dass das Berechnen der Texturkoordinaten am Schnittpunkt wirklich keine leichte Sache ist. Blitz stellt entsprechende PickedU/V leider nicht zur Verfügung, daher muss man es von Hand machen. Meine Lösung funktioniert wie folgt: Da man die UVs der Vertizes ja gegeben hat, muss man diese innerhalb des gegebenen (aber beliebigen) Dreicks interpolieren. Dazu verwendet man das Baryzentrische Koordinatensystem, welches einem nach Berechnung dreier Koordinaten diese Interpolation relativ leicht macht. Auf dem Wiki ist sogar eine Formel dazu. Problem ist aber, dass diese natürlich nur für 2D gilt; in unserem Fall hat man aber das Dreieck in 3D-Koordinaten gegeben - die Formel funktioniert also nicht. Nun hat man zwei Möglichkeiten: Erstens, das Dreieck mittels CameraProject ![]() Darum wählte ich die zweite Möglichkeit. Die vier Punkte (drei Eckpunkte und ein Schnittpunkt) liegen ja alle auf einer Ebene, darum ist es uns möglich, aus diesen 4 Punkten eine Ebene zu bauen und daraus dann ein lokales, orthonormales 2D Koordinatensystem zu basteln, in welches wir die 4 Punkte transformieren können. Dann haben wir wieder 2D-Koordinaten, können die Formel anwenden und haben zum Schluss unsere baryzentrischen Koordinaten, mit welchen wir dann die UV-Koordinaten berechnen können. Mein Code sieht so aus: BlitzBasic: [AUSKLAPPEN] Graphics3D 800, 600, 0, 2 Das Herumziehen der Textur funktioniert erstaunlich gut; nur dort, wo zwei angrenzende Dreiecke keine kontinuierlichen Texturkoordinaten haben, kommt es zu "Rucklern" - falls diese störend werden, kannst du sie unterbinden, indem du zusätzlich prüfst, ob in diesem Frame das gleiche Dreieck gepickt wurde wie im letzten. Was auch ganz cool ist, wenn man die Texture festhält und das Objekt mit den Pfeiltasten rotieren lässt. Der festgehaltene Pixel bleibt dann wirklich am selben Ort. Ich hoffe, das hilft dir weiter. |
||
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun |
![]() |
derAtomkeksehemals "Sethus" |
![]() Antworten mit Zitat ![]() |
---|---|---|
WooooooW ![]() Das ist die Lösung, die ich gesucht habe! Habe sie zwar noch nicht ganz verstanden, werde mich jetzt aber mal intensiv mit deinem Code und den geposteten Wiki-Artikeln beschäftigen, dann wird das schon. ![]() Vielen Dank!! Studierst du bzw. hast du etwas mathematisches studiert, oder woher weiß man sowas? ![]() |
||
![]() |
Noobody |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ich studiere im Moment Informatik im 3. Semester.
Den Teil mit den baryzentrischen Koordinaten wusste ich schon vorher (brauchte ich damals für einen kleinen Software-Rasterizer), und der Rest ging nach einem Semester Lineare Algebra eigentlich relativ fix von der Hand ![]() |
||
Man is the best computer we can put aboard a spacecraft ... and the only one that can be mass produced with unskilled labor. -- Wernher von Braun |
![]() |
derAtomkeksehemals "Sethus" |
![]() Antworten mit Zitat ![]() |
---|---|---|
Ja, autodidaktisch lernen ftw!! ![]() Kannst du mir vielleicht auch noch genau so schlau mit der Rotation von Texturen auf einer Surface helfen? Das muss auch nicht per Maus geschehen, das muss eingetippt werden. Ich lese da immer von Rotationsmatrizen... aber wie helfen mir die bei einem womöglich noch unregelmäßígen Netz aus Vertices? ![]() |
||
n-Halbleiter |
![]() Antworten mit Zitat ![]() |
|
---|---|---|
Öhm, Rotationsmatrizen haben die Eigenschaft, dass man mit ihnen beliebige Punkte um den Punkt (0,0) drehen kann. Die neuen Koordinaten des Punktes sind n = R * a (n = Matrix * alt). Wenn du nun eine Menge Punkte hast, multiplizierst du halt die Koordinaten jedes Punktes mit der Matrix, um die neuen Koordinaten zu erhalten. Mache das bei allen Punkten, und alle Punkte sind gedreht. (: | ||
mfg, Calvin
Maschine: Intel Core2 Duo E6750, 4GB DDR2-Ram, ATI Radeon HD4850, Win 7 x64 und Ubuntu 12.04 64-Bit Ploing! Blog "Die Seele einer jeden Ordnung ist ein großer Papierkorb." - Kurt Tucholsky (09.01.1890 - 21.12.1935) |
![]() |
derAtomkeksehemals "Sethus" |
![]() Antworten mit Zitat ![]() |
---|---|---|
Okay, habs, vielen Dank nochmal an alle ![]() ![]() |
||
Übersicht


Powered by phpBB © 2001 - 2006, phpBB Group