OpenGL -> line és sphere metszéspontja

OpenGL -> line és sphere metszéspontja
2005-02-26T15:41:24+01:00
2005-02-27T18:53:10+01:00
2022-10-23T20:55:36+02:00
Lacasrac
Halika!

A következőt kellene megoldanom:

Egy biliárd progiról van szó:

3d-s térben ugyebár kirajzolom a golyókat (sphere), és kirajzolok egy line-t, ami azt mutatja hova lököm a golyót. Kellene a 2 cucc közötti dolog. Tehát:

Hogyha metszésben vannak egymással. Ilyenkor kellene algoritmust futtatnom, amely a line-ból és a sphere-ből megmondja nekem, hogy hány fokos lesz az ütközés utáni állapot. (Melyik golyó hova fog menni az ütközés után)

A fizikájával tisztában vagyok, megírtam már az ütköző algoritmust, azt nem tudom megoldani, hogyan nézzem meg, hogy a line egyik "pontja" hozzáér -e egy sphere-hez. Jah és persze, CSAK az első sphere-hez (legközelebbi)

Tudna vki segíteni?
Mutasd a teljes hozzászólást!
OK, elszámoltam...

Ehelyett:
Dim v As Double = (-2 * A * (B - Balls(i).Z) - 2 * Balls(i).X)
legyen inkább ez:
Dim v As Double = (2 * A * (B - Balls(i).Z) - 2 * Balls(i).X)

Persze csak ha nem számoltam el.
Mutasd a teljes hozzászólást!

  • Nem vagyok tisztában a probléma minden részletével, de
    1. Asztal esetén ugyebár elég 2D-ben gondolkodni.
    2. Az egyenes két pontjából vagy egy pontjából és az irányából fel tudod írni az egyenes egyenletét y=Ax+B alakban.
    (Két pont esetén: y=(y2-y1)/(x2-x1)*(x-x1)+y1, míg pont és irány esetén: y=m(x-x1)+y1, ahol m=tg szög.)
    3. Fel tudod írni a golyót reprezentáló kör egyenletét: (x-a)^2+(y-b)^2-r^2=0, ahol (a,b) a középpont és r a sugár.
    4. Ebből a 2 behelyettesítéssel (ha nem írtam el semmit ):
    (A^2+1)x^2 + [-2A(B-b)-2a]x + (a^2+(B-b)^2-r^2 = 0, egyszerűbb jelöléssel: ux^2+vx+w=0, aminek a két megoldása:
    x=(-v +- sqrt(v^2-4uw))/2u, ebből az y=Ax+B-t felhasználva megvan a 2 y koordináta is.
    5. A gyök alatti rész vizsgálatával pedig:
    - <0 : nem metszik egymást,
    - =0 : érinti,
    - >0 : két metszéspont van.

    Kíváncsi vagyok, hány helyen számoltam el magam...
    Mutasd a teljes hozzászólást!
  • Az A,B mi?
    Mutasd a teljes hozzászólást!
  • Attól függ, hogy két pont alapján, vagy egy pont és egy szög alapján írod fel az egyenletet.
    Első esetben ezt kell ilyen alakra hozni:
    y=(y2-y1)/(x2-x1)*(x-x1)+y1
    Tehát: A=(y2-y1)/(x2-x1) és B=(y1-y2)/(x2-x1)*x1+y1
    Második esetben pedig ezt:
    y=m(x-x1)+y1
    Tehát: A=m és B=y1-m*x1
    Mutasd a teljes hozzászólást!

  • Dim i As Byte For i = 0 To 20 Dim A As Double = (targetZ - Balls(i).Z) / (targetX - Balls(i).X) Dim B As Double = (Balls(i).Z - targetZ) / (targetX - Balls(i).X) * Balls(i).X + Balls(i).Z Dim v As Double = (-2 * A * (B - Balls(i).Z) - 2 * Balls(i).X) Dim u As Double = (A ^ 2 + 1) Dim w As Double = Balls(i).X ^ 2 + (B - Balls(i).Z) ^ 2 - Balls(i).Rad ^ 2 Dim x1 As Double = (-v + Sqrt(v ^ 2 - 4 * u * w)) / 2 * u Dim x2 As Double = (-v - Sqrt(v ^ 2 - 4 * u * w)) / 2 * u Dim z1 As Double = A * x1 + B Dim z2 As Double = A * x2 + B Gl.glPushMatrix() Gl.glDisable(Gl.GL_TEXTURE_2D) Gl.glDisable(Gl.GL_LIGHTING) Gl.glEnable(Gl.GL_BLEND) Gl.glBlendFunc(Gl.GL_SRC_ALPHA, Gl.GL_ONE_MINUS_SRC_ALPHA) Gl.glColor4f(0.2, 0.8, 0.2, 0.8) Gl.glLineWidth(1) Gl.glBegin(Gl.GL_LINES) Gl.glVertex3f(x1, camera(4), z1) Gl.glVertex3f(x2, camera(4), z2) Gl.glEnd() Gl.glDisable(Gl.GL_BLEND) Gl.glEnable(Gl.GL_LIGHTING) Gl.glEnable(Gl.GL_TEXTURE_2D) Gl.glPopMatrix() Next i

    Mit rontok el?
    Mutasd a teljes hozzászólást!
  • 1. Egyszer te is végigszámolhatnád, hajlamos vagyok az általam elszámolt dolgokat nem észrevenni.
    2. Azt nem kell megvizsgálni, hogy a gyök alatt nincs-e véletlenül negatív szám (azaz nincs metszéspont)?
    3. Mi az a camera(4)? Az asztal síkja?
    4. Ez mit csinálna? Összekötné a két metszéspontot egy vonallal???
    Mutasd a teljes hozzászólást!
  • Hát ezaz:))))

    Nekem nem ez kéne, hanem, hogyha egy golyóhoz ér a LINE, akkor...

    Szal most azt csinálja, hogy az össz. golyó +a target metszéspontot összeköti:(

    If Math.Sqrt(v ^ 2 - 4 * u * w) >= 0 Then

    közben ez is benne van már.

    "3. Mi az a camera(4)? Az asztal síkja?"

    Bizony..

    és azért X,Z, mert egy kicsit el van variálva pár dolog.

    Mutasd a teljes hozzászólást!
  • Szal most azt csinálja, hogy az össz. golyó +a target metszéspontot összeköti:(

    Tehát akkor jelenleg éppen mit is csinál?

    Még azt kellene lekezelni, hogy a két metszéspont közül meg kellene keresni a közelebbit...
    Tényleg, a targetX és targetZ micsoda?

    és azért X,Z, mert egy kicsit el van variálva pár dolog

    Nálam is az y szokott lenni a felfele, ebben nincs semmi furcsa...
    Mutasd a teljes hozzászólást!
  • "Tényleg, a targetX és targetZ micsoda?"

    Nos:

    Van a dákó: és van ugyebár egy vonal, ami mutatja, hogy hova fog menni a fehér golyó. A targetX, Z gyakorlatilag a vég pontja, a kezdő pont a balls(0).x és Z. Ami ugye a fehér koord.-ja.

    A targetX/Z pedig,ha nagyobb a vonal,mint az asztal, akkor "levágja" az asztal méretére.. Hogy ne menjen ki belőle..

    Szal mit rontok el?
    Mutasd a teljes hozzászólást!
  • Azt még mindig nem írtad le pontosan, hogy most mit csinál.
    Mutasd a teljes hozzászólást!
  • Mutasd a teljes hozzászólást!
  • Na egyszer: az egyenes egyenletének felírásánál a (targetX,targetZ) és a (Balls(i).X, Balls(i).Z) pontokat használod fel, tehát a fehér golyó "becsapódási helyét" és egy másik golyó középpontját kötöd össze. Ennek mi értelme? Nem mindig a fehér golyó középpontjának kellene lennie a második pontnak?
    Másodszor ez:
    Gl.glBegin(Gl.GL_LINES) Gl.glVertex3f(x1, camera(4), z1) Gl.glVertex3f(x2, camera(4), z2) Gl.glEnd()
    Összeköti a két metszéspontot? Bár akkor nemtudom miért azt a képet adja, amit ad...
    Mutasd a teljes hozzászólást!
  • aham, az első hibát megtaláltam.

    De akkor ehelyett:

    Gl.glVertex3f(x1, camera(4), z1)
    Gl.glVertex3f(x2, camera(4), z2)

    Mit írjak?

    gondolom balls(i).x, z is kéne bele..
    Mutasd a teljes hozzászólást!
  • Attól függ, hova akarsz vonalat húzni.
    A metszéspont és a fehér golyó pozíciója közé? Vagy hova?
    Mutasd a teljes hozzászólást!
  • Szal azt szeretném megcsinálni, hogy oda húzzon vonalat amelyre a megütött golyó elfog mozdulni.

    Tehát az első x,z az biztos hogy annak a golyónak az x,y-ja.

    A második pedig...?
    Mutasd a teljes hozzászólást!
  • Na látod, ez már jó kérdés. Amit ezzel kiszámolsz, az a vonal és a kör metszéspontja. Hogy merre fog aztán a megütött golyó elmozdulni, arra már nem tudok válaszolni, de gondolom ezt kellene a metszéspontból számolni, tehát nem a metszéspontot kellene valami mással összekötni, hanem abból kapod meg az elmozdulás irányát...
    Mutasd a teljes hozzászólást!
  • Igen, köszi, erre van forrásom, meg is próbálom:)



    Dim A As Double = (targetZ - Balls(0).Z) / (targetX - Balls(0).X) Dim B As Double = (Balls(0).Z - targetZ) / (targetX - Balls(0).X) * Balls(0).X + Balls(0).Z Dim v As Double = (-2 * A * (B - Balls(i).Z) - 2 * Balls(i).X) Dim u As Double = (A ^ 2 + 1) Dim w As Double = Balls(i).X ^ 2 + (B - Balls(i).Z) ^ 2 - Balls(i).Rad ^ 2 Dim x1 As Double = (-v + Sqrt(v ^ 2 - 4 * u * w)) / 2 * u Dim x2 As Double = (-v - Sqrt(v ^ 2 - 4 * u * w)) / 2 * u Dim z1 As Double = A * x1 + B Dim z2 As Double = A * x2 + B If Math.Sqrt(v ^ 2 - (4 * u * w)) >= 0 Then

    De ez eddig jó nem?
    Mutasd a teljes hozzászólást!
  • Megálmodtam a megoldást.

    Az egyenes egyenletét a következő két pontból kell felírni: a fehér golyó középpontja és a várható becsapódási pont (targetX, targetZ). A kör sugara a golyó sugarának kétszerese kell legyen, hiszen az egyenes csak a fehér golyó középpontjának útja, és attól még lehet, hogy ütköznek, hogy ez az egyenes nem metszi a kört. Tehát a sugár 2x-ese kell.
    Ebből kell kiszámolni a két metszéspontot, és utána kell ezek közül a fehér golyó középpontjához (jelöljük (wx,wz)-vel) közelebbi:
    (wx-x1)^2+(wz-z1)^2 és (wx-x2)^2+(wz-z2)^2 közül a kisebbik.
    Így a mgütött golyó véleményem szerint a saját középpontja és a (közelebbi) metszéspont által meghatározott egyenesen fog elmozdulni...
    Szerintem...
    Mutasd a teljes hozzászólást!
  • De ez eddig jó nem?

    Ha módosítod a sugarat az előbb elmondottak szerint, akkor jó lesz...
    Mutasd a teljes hozzászólást!

  • Dim R As Double = Balls(0).Rad * 2 Dim A As Double = (targetZ - Balls(0).Z) / (targetX - Balls(0).X) Dim B As Double = (Balls(0).Z - targetZ) / (targetX - Balls(0).X) * Balls(0).X + Balls(0).Z Dim v As Double = (-2 * A * (B - Balls(i).Z) - 2 * Balls(i).X) Dim u As Double = (A ^ 2 + 1) Dim w As Double = Balls(i).X ^ 2 + (B - Balls(i).Z) ^ 2 - R ^ 2 Dim x1 As Double = (-v + Sqrt(v ^ 2 - 4 * u * w)) / (2 * u) Dim x2 As Double = (-v - Sqrt(v ^ 2 - 4 * u * w)) / (2 * u) Dim z1 As Double = (A * x1) + B Dim z2 As Double = (A * x2) + B ... If Math.Sqrt(v ^ 2 - (4 * u * w)) >= 0 Then ... Dim d1 As Double = Sqrt((Balls(0).X - x1) ^ 2 + (Balls(0).Z - z1) ^ 2) Dim d2 As Double = Sqrt((Balls(0).X - x2) ^ 2 + (Balls(0).Z - z2) ^ 2) Dim Dist As Double, dx, dz As Double If d1 < d2 Then Dist = d2 dx = x1 : dz = z1 Else Dist = d1 dx = x2 : dz = z2 End If Gl.glLineWidth(4) Gl.glBegin(Gl.GL_LINES) Gl.glVertex3f(Balls(i).X, camera(4), Balls(i).Z) Gl.glVertex3f(Balls(i).X + dx, camera(4), Balls(i).Z + dz) Gl.glEnd()

    Biztos jók a képletek?

    Mert én is elkezdtem itthon számolni, de picikét durva volt:)
    Mutasd a teljes hozzászólást!
  • brown
    0
    -32
    -0,831649157494811
    -33,833455626303


    Ez a debug szerint.

    1: balls(i).x
    2: balls(i).z
    3: dx
    4: dz

    Jahm most pl olyat is csinál, hogy ráirányítom a sárgára, és a zöldből rajzol... És fordítva:)))
    Mutasd a teljes hozzászólást!
  • Ez szerintem nem jó:
    Gl.glVertex3f(Balls(i).X, camera(4), Balls(i).Z) Gl.glVertex3f(Balls(i).X + dx, camera(4), Balls(i).Z + dz)

    Ugyebár a golyó középpontja az egyik pont, a másik pedig ennek az eltolása a (Balls(i).X-dx, Balls(i).Z-dz) vektor számszorosával (igény szerint), tehát pl.
    Gl.glVertex3f(Balls(i).X, camera(4), Balls(i).Z) Gl.glVertex3f(Balls(i).X + 3*(Balls(i).X-dx), camera(4), Balls(i).Z + 3*(Balls(i).Z-dz))

    A képleteket még1x átszámolom...
    Mutasd a teljes hozzászólást!

  • (x^2+balls(i).x^2-2*x*balls(i).x) + ( ((targetz-balls(0).z)/(targetx-balls(0).x)*(x-balls(0).x)+balls(0).z))^2+balls(i).z^2-2*((targetz-balls(0).z)/(targetx-balls(0).x)*(x-balls(0).x)+balls(0).z))-balls(i).rad=0

    Nekem ez a fő képlet, ha ki nem maradt 1-2 zárójel. Ebből kellene x12.
    Mutasd a teljes hozzászólást!
  • OK, elszámoltam...

    Ehelyett:
    Dim v As Double = (-2 * A * (B - Balls(i).Z) - 2 * Balls(i).X)
    legyen inkább ez:
    Dim v As Double = (2 * A * (B - Balls(i).Z) - 2 * Balls(i).X)

    Persze csak ha nem számoltam el.
    Mutasd a teljes hozzászólást!
  • Mutasd a teljes hozzászólást!
  • Hát ha jól dolgoztam fel ezt a hatalmas hieroglifatömeget, akkor nagyjából helyes a képleted, csak a végén akkor rad*2, és az is a négyzeten...
    Mutasd a teljes hozzászólást!
  • Hallod te matematikus vagy?:)

    Én eskü nem tudtam visszaszámolni...
    Mindig belezavarodtam:(


    Köszi a megoldást.
    Mutasd a teljes hozzászólást!
  • Programtervező matematikus. De a matematikus csak olyan dísz. Bár néhány tanár szerint nem az...
    Mutasd a teljes hozzászólást!
  • Tudnál még helpelni? A koccanás algoritmusom elég érdekesen műxik..
    Mutasd a teljes hozzászólást!
  • Fejtsd ki!
    Mutasd a teljes hozzászólást!
Tetszett amit olvastál? Szeretnél a jövőben is értesülni a hasonló érdekességekről?
abcd