Zobrazit předchozí téma :: Zobrazit následující téma |
Autor |
Zpráva |
neonfish

Založen: 15. 04. 2010 Příspěvky: 5
|
Zaslal: 20. duben 2010, 12:43:18 Předmět: 3D engine + scripting |
|
|
Zdravim vas vsetkych.
Riesim jeden problem uz dost dlho a nejako sa mi to nedari .Aj som hladal na tomto fore no nie celkom uspesne.Mam jednoduchy 3d engine.Scena sa sklada z jednej velkej Gule na korej je textura oblohy.V strede gule je akoze zem.Tenky kvader s texturou travy.dasli model je krizovatka a na krizovatke je auto.Cely engine pouziva jazyk ruby.A scena sa da spustit pomocou ruby scriptu ,ktory je spustany enginom. Samotny script obsahuje naloadovanie modelov a pracu snimi.;Napriklad blikanie objektov,rotacia,orientacia,a aj pohyb v nejakej forma sa mi podaril spravit.Problem mam s otacavym pohybom ,cize pohybom po krivej trajektorii.Potrebujem donutit to auto aby vedelo na krizovatke odbocit.Pozeral som teoriu k tomu na nete.Metoda runge kutta a Bezierove krivky a Bspline krivky.Lenze sa mi to zda priliz zlozite .Potreboval by som aby mi niekto vysvetlil ako sa v principe programuje takyto typ pohybu.Potrebujem velmi jednoduchy pohyb z bodu A do bodu B ale po krivke.Dam sem moj kod na pohyb a rotaciu.Aby ste videli ako to vypada v tom ruby.
takto vyzera jednoduchy script a scena.Jazyk RUBY je podobny jazyku C++ takze by ste to mali aj chapat celkom podla mna.Ak nie pytajte sa.
Nasledujuci script vykona blikanie auta potom blika krizovatka, potom sa auto presunie a zacne rotovat donekonecna okolo osi Z rychlostou 100
kód: |
$camera = ENGINE::DefaultCamera(); ##cita kameru
$camera.position(1,-25,5);
$camera.orientation(1,1,-9);
$cesta = ENGINE::LoadModel("Road_08junction.bin"); ##cita model cesty
$cesta.SetScale(0.01,0.01,0.01);
$cesta.position(1,1,-9.9);
$ground = ENGINE::LoadModel("grassground.bin"); ##zem s trravnikom
$ground.pz = -10.0;
$sky = ENGINE::LoadModel("sky.bin"); ###gula s oblohou
$sky.SetScale(1,1,1);
$auto3 = ENGINE::LoadModel("blue2.bin"); ## modre auto
$auto3.SetScale(2,2,2);
$auto3.position(2,10,-9.9);
########################### Global variables
$scene_id = 0;
$scene_count = 0;
$blink_timer=0;
$blink_count=0;
$wait_time = 1.0;
########################### end of global variables
def BlinkObject(object,fin=1) ##metoda na blikanie objektu/modelu
$BLINKRATE=0.3;
$BLINKCOUNT=6;
finished = false;
$blink_timer = $blink_timer + $FRAMETIME;
if ($blink_timer > $BLINKRATE) then
if (object.visible == 1) then object.visible = 0 else object.visible = 1 end
$blink_timer =0;
$blink_count = $blink_count + 1;
end
if($blink_count > (2*$BLINKCOUNT)) then
finished=true; $blink_count=0; $blink_timer =0;
if(fin==0) then object.visible = 0 else object.visible = 1 end
end
return finished;
end
def Wait(time = 5.0)
finished = false;
$wait_time = $wait_time - (1.0/time)*$FRAMETIME;
if($wait_time <= 0.0) then
$wait_time = 1.0;
finished = true;
end
return finished;
end
##########################pohyb camery a objektov
###########
def CameraDirection(object,x,y,z,speed=1)
pdx = (object.ox - x).abs;
pdy = (object.oy - y).abs;
pdz = (object.oz - z).abs;
if(pdx<=0.001 && pdy<=0.001 && pdz<=0.001) then return
true
end
dirx = 1.0;
diry = 1.0;
dirz = 1.0;
dx = x - object.ox;
dy = y - object.oy;
dz = z - object.oz;
if(dx<0.0) then dirx = -1.0 end
if(dy<0.0) then diry = -1.0 end
if(dz<0.0) then dirz = -1.0 end
deltax = speed * dirx * $FRAMETIME;
deltay = speed * diry * $FRAMETIME;
deltaz = speed * dirz * $FRAMETIME;
max = dx.abs;
if(dy.abs > max) then max = dy.abs end
if(dz.abs > max) then max = dz.abs end
if(max == dx.abs) then
deltay = deltay * (dy.abs/dx.abs);
deltaz = deltaz * (dz.abs/dx.abs);
elsif(max == dy.abs) then
deltax = deltax * (dx.abs/dy.abs);
deltaz = deltaz * (dz.abs/dy.abs);
elsif(max == dz.abs) then
deltax = deltax * (dx.abs/dz.abs);
deltay = deltay * (dy.abs/dz.abs);
end
object.ox = object.ox + deltax;
object.oy = object.oy + deltay;
object.oz = object.oz + deltaz;
if(dirx<0.0) then
if(object.ox <= x) then object.ox = x end
else
if(object.ox >= x) then object.ox = x end
end
if(diry<0.0) then
if(object.oy <= y) then object.oy = y end
else
if(object.oy >= y) then object.oy = y end
end
if(dirz<0.0) then
if(object.oz <= z) then object.oz = z end
else
if(object.oz >= z) then object.oz = z end
end
pdx = (object.ox - x).abs;
pdy = (object.oy - y).abs;
pdz = (object.oz - z).abs;
if(pdx<=0.001 && pdy<=0.001 && pdz<=0.001) then return
true
else return false end
end
def MoveCamera(object,px,py,pz,dx,dy,dz,speed=1)
finishedmove = MoveObject(object,px,py,pz,speed);
finisheddirection = CameraDirection(object,dx,dy,dz,speed);
finished = finishedmove & finisheddirection;
return finished;
end
def MoveObject(object,x,y,z,speed=1, condition=(object.py<-10))
deltax = speed * x * $FRAMETIME;
deltay = speed * y * $FRAMETIME;
deltaz = speed * z * $FRAMETIME;
object.px = object.px + deltax;
object.py = object.py + deltay;
object.pz = object.pz + deltaz;
return condition;
end
################### NASLEDUJUCA CAST VYKONAVA SAMOTNU AKCIU v kazdej jednej scene.
def ENGINE::Actions
$scene_id==0;
$scene_count = $scene_count + $FRAMETIME;
if ($scene_id==0) then
if(BlinkObject($auto3)) then $scene_count=0;
$scene_id=$scene_id+1;
end
end
if ($scene_id==1) then
if(BlinkObject($cesta)) then $scene_count=0;
$scene_id=$scene_id+1;
end
end
if ($scene_id==2) then
if(MoveObject($auto3,0,-1,0,7)) then $scene_count=0;
$scene_id=$scene_id+1;
end
end
if ($scene_id==3) then
if (CameraDirection($auto3,1,1,-5,100)) then $scene_count=0;
$scene_id=$scene_id+1;
end
end
end
|
|
|
Návrat nahoru |
|
 |
perry

Založen: 28. 07. 2009 Příspěvky: 879
|
Zaslal: 20. duben 2010, 14:20:51 Předmět: |
|
|
Pokud to chápu správně, chceš aby to auto jelo po nějaký trati...
Něco podobného mám pro kameru, která prolétává scénou. Uděláš sérii klíčových bodů, na které má to auto dojet. Nejlehčí řešení (ale ne moc pěkný pohyb) je, že se body mezi se pak interpolují lineárně.
Takovýhle pohyb bude ale pro auto dost ošklivý, pokud budeš mít málo bodů. Lepší je naprogramovat Spline interpolaci z daných bodů a ta ti vytvoří křivku, po které auto pojede.
Pro kameru jsem čerpal odtud:
http://graphicsrunner.blogspot.com/2008/05/camera-animation-part-i.html (Má to i druhý díl právě se Spline interpolací) |
|
Návrat nahoru |
|
 |
neonfish

Založen: 15. 04. 2010 Příspěvky: 5
|
Zaslal: 21. duben 2010, 10:11:14 Předmět: |
|
|
Ano presne.POtrebujem aby auto s pozicie A (x,y,z) sa pomocou metody dokazalo dostat do bodu B(x,y,z) cez obluk.Cize pises ,ze potrebujem si urcit viacej bodov.Alebo stacia 2 body? Vychodzia poziia a koncova alebo potrebujem aj v strede (obluku) pohybu si urcit nejake body?Mne sa zda ,ze by mali stacit dva tie body nie?
Viete mi niekto naspiat kratky strukturalny postup ako by to malo vypadat aj so vstupmi?Nemam skusenosti s takouto formou ptreto sa obraciam na vasu komunitu. |
|
Návrat nahoru |
|
 |
neonfish

Založen: 15. 04. 2010 Příspěvky: 5
|
Zaslal: 21. duben 2010, 10:16:06 Předmět: |
|
|
V podstate ja potrebujem menit aj rotaciu ..cize to ma byt akoze v kazdom FRAMETIME sa musim posunut a otocit ..alebo skor otocit a posunut?lebo ked ide o posun po trajektorii oblej ..ja potrebujem aby auto aj smerovalo v smere pohybu |
|
Návrat nahoru |
|
 |
Ladis

Založen: 18. 09. 2007 Příspěvky: 1537 Bydliště: u Prahy
|
Zaslal: 21. duben 2010, 10:26:38 Předmět: |
|
|
Odpověděl jsi si už v původní otázce - jsou na ty ty algoritmy pro kreslení křivek (např. Bézierova křivka). Nic jednoduššího asi nenajdeš. Zde jsem vygooglil stránku, kde máš krátký ukázkový procedurální kód. Jedinou další alternativou je mít úplně obyčejnou lineární interpolaci a těch klíčových bodů mít víc. Mám to tak při ukládání trajektorie hráče v mé hře Mars Racer (ukládá si pozici a otočení a při přehrávání lineárně interpoluje). _________________ Award-winning game developer |
|
Návrat nahoru |
|
 |
perry

Založen: 28. 07. 2009 Příspěvky: 879
|
Zaslal: 21. duben 2010, 11:14:52 Předmět: |
|
|
No ještě mě napadla jedna možnost.. pokud přesně víc, že chceš aby auto jelo po dráze: přímka, oblouk, přímka.. můžeš zkusit použít 4 body (+ 1 stred oblouku)..
AB, CD ti urci zacatek (konec) primek a mezi to vyplnis kruznici (elipsou).. není potřeba interpolací, protože obojí má přesné rovnice |
|
Návrat nahoru |
|
 |
neonfish

Založen: 15. 04. 2010 Příspěvky: 5
|
Zaslal: 22. duben 2010, 08:22:38 Předmět: |
|
|
perry napsal: |
AB, CD ti urci zacatek (konec) primek a mezi to vyplnis kruznici (elipsou).. není potřeba interpolací, protože obojí má přesné rovnice |
a je to podmienka aby tam boli tie priamky? Co keby som jednoducho iba tu krucnicu(elipsu) nejako pouzil? Cize v tom pripade Mi staci bod zaciatku obluku a bod konca + stredovy bod?
A ake su tie rovnice.Mysel si matematicku rovnicu kruznice?
(x-m)2 + (y-n)2 = r2
prosim objasnite mi to .Dakujem pekne zatial za odpovede. |
|
Návrat nahoru |
|
 |
quas4
Založen: 18. 10. 2007 Příspěvky: 199
|
Zaslal: 22. duben 2010, 11:57:02 Předmět: |
|
|
perry napsal: |
AB, CD ti urci zacatek (konec) primek a mezi to vyplnis kruznici (elipsou).. není potřeba interpolací, protože obojí má přesné rovnice
|
Jestli muzu poradit tak se touto cestou nevydavej! Nemas zaruceno ze je prubeh spojity a tuna dalsich problemu. "Presnou rovnici" (existuje i nepresna?) maji i interpolacni nebo aproximacni krivky a urcite bych doporucil si vybrat nekterou z nich ktera ti vyhovuje. V http://apps.facebook.com/hispeedracing (uz jsem jak Ladis ) jsem jednoduse pouzil bezier kubiky naskladane "za sebe" a body P1 a P2 (viz obrazek http://en.wikipedia.org/wiki/B%C3%A9zier_curve ) jsou dopocitavany automaticky - uzivatel v editoru taha jen P0 a P3. Smer v libovolnem bode krivky je urcen tangentou (derivace). Klidne vystavim code-snippet. |
|
Návrat nahoru |
|
 |
neonfish

Založen: 15. 04. 2010 Příspěvky: 5
|
Zaslal: 22. duben 2010, 17:04:36 Předmět: |
|
|
quas4 napsal: |
perry napsal: |
AB, CD ti urci zacatek (konec) primek a mezi to vyplnis kruznici (elipsou).. není potřeba interpolací, protože obojí má přesné rovnice
|
Jestli muzu poradit tak se touto cestou nevydavej! Nemas zaruceno ze je prubeh spojity a tuna dalsich problemu. "Presnou rovnici" (existuje i nepresna?) maji i interpolacni nebo aproximacni krivky a urcite bych doporucil si vybrat nekterou z nich ktera ti vyhovuje. V http://apps.facebook.com/hispeedracing (uz jsem jak Ladis ) jsem jednoduse pouzil bezier kubiky naskladane "za sebe" a body P1 a P2 (viz obrazek http://en.wikipedia.org/wiki/B%C3%A9zier_curve ) jsou dopocitavany automaticky - uzivatel v editoru taha jen P0 a P3. Smer v libovolnem bode krivky je urcen tangentou (derivace). Klidne vystavim code-snippet. |
ahoj mozes prosim ta vystavit ten kod ...alebo mi ho poslat nech si to prestudujem?
vdaka pekne |
|
Návrat nahoru |
|
 |
perry

Založen: 28. 07. 2009 Příspěvky: 879
|
Zaslal: 22. duben 2010, 18:06:47 Předmět: |
|
|
Podle mě používat beziera nebo spliny na něco u čeho znáš na 100% tvar je zbytečný kalibr (+ navíc abys ten tvar dostal, budeš potřebovat rozhodně víc bodů, ze dvou bodů ti nikdy polokruh u spline nevypadne)... kdybych měl oválnou dráhu a chtěl aby po ní jezdilo auto, tak jí popíšu 2 přímkama a 2 polokružnicema. Tím dostanu relativně přesný popis (narozdíl od aproximace se stejným počtem bodů).
Beziér je taky dobrá volba, ale nevýhoda je, že musíš mít řídící body...
Nicméně, pokud to chceš univerzální a chceš si s tim pohrát, takl bych doporučil asi spline. Pokud chceš nechat auto jezdit dokola (nebo na oválu) použil bych rovnice z analytické geometrie.
----
Zaručení spojitosti moc nechápu.. spojitý to bude, když budeš mít koncový bod = krajní bod a zbytek je spojitá funkce
citace: |
"Presnou rovnici" (existuje i nepresna?) maji i interpolacni nebo aproximacni krivky a |
Interpolační křivky mají sice přesné rovnice, ale jejich přesnost je relativní. Proto je to aproximace. Kdežto rovnice přímky, kružnice je 100% jasná, že vypočteš +- každý bod a dostaneš kružnici (nepočítam zaokrouhlovací chyby)... |
|
Návrat nahoru |
|
 |
quas4
Založen: 18. 10. 2007 Příspěvky: 199
|
Zaslal: 22. duben 2010, 18:31:20 Předmět: |
|
|
nasel jsem python implementaci, kterou jsem hodne zjednodusil + pyglet aplikace:
kód: |
from pyglet.gl import *
import math
class Vec2:
def __init__(self, x, y): self.x = x; self.y = y
def __mul__(self, s): return Vec2(self.x * s, self.y * s)
def __div__(self, s): return Vec2(self.x / s, self.y / s)
def __add__(self, o): return Vec2(self.x + o.x, self.y + o.y)
def __sub__(self, o): return Vec2(self.x - o.x, self.y - o.y)
def length(self): return math.sqrt(self.x ** 2 + self.y ** 2)
def normalized(self):
ret = Vec2(self.x, self.y)
l = 1.0 / ret.length()
ret.x *= l
ret.y *= l
return ret
class Spline:
def __init__(self, pts):
self.pts = pts
self.recalc_handles()
def recalc_handles(self): # podle pts dopocita tzv. handles (coz jsou prave zminene P1 a P2)
self.left_handles = [None] * len(self.pts)
self.right_handles = [None] * len(self.pts)
for i in range(len(self.pts)):
if i == 0: previ = - 1
else: previ = i - 1
if i == len(self.pts) - 1: nexti = -1
else: nexti = i + 1
self.calc_handles(i, previ, nexti)
def calc_handles(self, i, previ, nexti):
p2 = self.pts[i]
if previ == -1:
p3 = self.pts[nexti]
pt = p2 * 2 - p3
p1 = pt
else: p1 = self.pts[previ]
if nexti == -1:
pt = p2 * 2 - p1
p3 = pt
else: p3 = self.pts[nexti]
d = p2 - p1
len1 = d.length()
d1 = p3 - p2
len2 = d1.length()
if len1 == 0: len1 = 1.0
if len2 == 0: len2 = 1.0
v = d1 / len2 + d / len1
l = 2.5614 * v.length()
if l:
if len1 > 5.0 * len2: len1 = 5.0 * len2
if len2 > 5.0 * len1: len2 = 5.0 * len1
len1 /= l
self.left_handles[i] = self.pts[i] - v * len1
len2 /= l
self.right_handles[i] = self.pts[i] + v * len2
def evaluate(self, t):
ln = len(self.pts)
assert(ln > 0)
if ln == 1 or t <= 0: return self.pts[0]
if t >= 1: return self.pts[ln - 1]
if ln == 2: return self.pts[0] + (self.pts[1] - self.pts[0]) * t # 2 body -> usecka
t *= ln - 1
i = int(t)
t -= i
i %= ln
return self.bezier4(self.pts[i], self.right_handles[i],
self.left_handles[i + 1], self.pts[i + 1], t)
def evaluate_tan(self, t):
ln = len(self.pts)
assert(ln >= 2)
if ln == 2: return (self.pts[1] - self.pts[0]).normalized()
if t < 0: t = 0.0
if t >= 1: t = 1.0
t *= (ln - 1)
i = int(t)
t -= i
i %= ln
if i == ln - 1:
return -self.bezier4_tan(self.pts[ln - 1], self.left_handles[ln - 1],
self.pts[ln - 2], self.right_handles[ln - 2], 0)
return self.bezier4_tan(self.pts[i], self.right_handles[i],
self.left_handles[i + 1], self.pts[i + 1], t)
def bezier4(self, p0, p1, p2, p3, t):
t0 = (1 - t) * (1 - t) * (1 - t)
t1 = 3 * t * (1 - t) * (1 - t)
t2 = 3 * t * t * (1 - t)
t3 = t * t * t
return p0 * t0 + p1 * t1 + p2 * t2 + p3 * t3
def bezier4_tan(self, p0, p1, p2, p3, t):
t0 = -3 * (1 - t) * (1 - t)
t1 = 3 * (1 - t) * (1 - t) - 6 * (1 - t) * t
t2 = 6 * (1 - t) * t - 3 * t* t
t3 = 3 * t * t
return (p0 * t0 + p1 * t1 + p2 * t2 + p3 * t3).normalized()
window = pyglet.window.Window()
curve = Spline([Vec2(-3, -2), Vec2(-1, 2), Vec2(0, -1), Vec2(3, -2)])
@window.event
def on_draw():
glClear(GL_COLOR_BUFFER_BIT)
glMatrixMode(GL_PROJECTION)
glLoadIdentity()
glOrtho(-4, 4, -3, 3, -1, 1)
glMatrixMode(GL_MODELVIEW)
glLoadIdentity()
# samotna krivka:
glColor3f(1, 1, 1)
glBegin(GL_LINE_STRIP)
t = 0.0
while t <= 1 + 1.0 / 100:
pt = curve.evaluate(t)
glVertex2f(pt.x, pt.y)
t += 1.0 / 100
glEnd()
# tangenty:
glColor3f(1, 0, 0)
glBegin(GL_LINES)
t = 0.0
while t <= 1:
pt = curve.evaluate(t)
pt2 = pt + curve.evaluate_tan(t)
glVertex2f(pt.x, pt.y)
glVertex2f(pt2.x, pt2.y)
t += 1.0 / 10
glEnd()
glColor3f(1, 1, 0)
glPointSize(10)
glBegin(GL_POINTS)
for p in curve.pts: glVertex2f(p.x, p.y)
glEnd()
pyglet.app.run()
|
|
|
Návrat nahoru |
|
 |
quas4
Založen: 18. 10. 2007 Příspěvky: 199
|
Zaslal: 23. duben 2010, 03:07:53 Předmět: |
|
|
perry napsal: |
Podle mě používat beziera nebo spliny na něco u čeho znáš na 100% tvar je zbytečný kalibr |
obecne souhlasim. jen bych odkazal na (bezier vs spline): http://en.wikipedia.org/wiki/B%C3%A9zier_spline
perry napsal: |
Zaručení spojitosti moc nechápu.. spojitý to bude, když budeš mít koncový bod = krajní bod a zbytek je spojitá funkce |
vyznam "spojity" o kterem jsem mluvil znamena ze existuje prvni derivace v celem intervalu.
citace: |
citace: |
"Presnou rovnici" (existuje i nepresna?) maji i interpolacni nebo aproximacni krivky a |
Interpolační křivky mají sice přesné rovnice, ale jejich přesnost je relativní. Proto je to aproximace. |
zde jsem se bohuzel ztratil. znamena to ze aproximace je to same jako interpolace s relavantni presnosti?  |
|
Návrat nahoru |
|
 |
perry

Založen: 28. 07. 2009 Příspěvky: 879
|
Zaslal: 23. duben 2010, 06:55:14 Předmět: |
|
|
citace: |
citace:
citace:
"Presnou rovnici" (existuje i nepresna?) maji i interpolacni nebo aproximacni krivky a
Interpolační křivky mají sice přesné rovnice, ale jejich přesnost je relativní. Proto je to aproximace.
zde jsem se bohuzel ztratil. znamena to ze aproximace je to same jako interpolace s relavantni presnosti? Smile
|
No myslel jsem to tak, že prostě i když mám hromadu bodů, tak aproximace je vždycky jenom aproximace, tzn. že nemusí přesně odpovídat tomu, co ty body ve skutečnosti popisují (a čím míň bodů bude, tím míň přesný to bude)..  |
|
Návrat nahoru |
|
 |
Mem

Založen: 28. 07. 2007 Příspěvky: 1959 Bydliště: Olomouc
|
Zaslal: 23. duben 2010, 07:46:53 Předmět: |
|
|
perry napsal: |
Interpolační křivky mají sice přesné rovnice, ale jejich přesnost je relativní. Proto je to aproximace. |
To si trochu pleteš pojmy, v geometrii to jednoznačně znamená:
- interpolační křivky - křivka přímo prochází řídícími body (b-spline apod.)
- aproximační křivky - řídící body jsou mimo křivku (bézier apod.)
Pro tebe jako uživatele to má podstatný vliv jen na tom, jak dobře se ti budou křivky modelovat (kde budeš těmi řídícími body tahat a jak budeš řešit spojování).
V obou případech můžeš tu křivku modelovat s libovolnou přesností, bude pořád i vizuálně hladká, nebude nikam uskakovat (tolik k tomu dojmu "aproximace"). Spojitost už kolega taky vysvětlil, to, že se oblouk kružnice napojí ve stejném bodě na úsečku neznamená, že tam bude C1(?)-spojité místo ("hladký přechod"), to bude jen ve speciálních případech. U toho příkladu s oválem by to zřejmě mělo fungovat, pokud úsečky budou rovnoběžky a napojí se na přesné půlkružnice, ale obecně si musíš spočítat tečnu a ztotožnit jí s tou úsečkou, na kterou se chceš napojit... _________________
 |
|
Návrat nahoru |
|
 |
|