Volledige versie bekijken : 3D rotaties?
TjOeNeR
%Europe/Berlin %495 %2005, 12:53
Weet er iemand de juiste formules voor 3D rotaties?
//Rotate around X axis
tmp.y = (cosx * vec.y) - (sinx * vec.z);
tmp.z = (sinx * vec.y) + (cosx * vec.z);
//Rotate around Y axis
tmp.x = (siny * tmp.z) + (cosy * vec.x);
rot.z = (cosy * tmp.z) - (siny * vec.x);
//Rotate around Z axis
rot.x = (cosz * tmp.x) - (sinz * tmp.y);
rot.y = (sinz * tmp.x) + (cosz * tmp.y);
Want deze geven een klein foutje, de Y-as zelf, wordt meegedraaid door de X-as.
Nogal moeilijk om uit te leggen, een voorbeeld is hier beter op zijn plaats...
http://users.skynet.be/tjoener/buggy/testVector.html
De Y-as zelf veranderd in een Z-as als die gedraaid wordt.
Nogal redelijk ambetant...
Edit:
Muis links-rechts = draaing X
Muis omhoog-omlaag = draaing Y
kH_
%Europe/Berlin %528 %2005, 13:41
De formules kloppen wel. Waar jij tegenaanloopt heeft te maken met de rotatie van het coordinatensysteem. Normaal, als je dus voor zowel de X,Y,als de Z hoek een rotatiehoek van 0 geeft, dan 'kijkt' de kubus je dus gewoon aan. Stel...je roteert je kubus 90 graden om de Y-as.
Op dat moment roteert je X-as van het coordinaten systeem dus ook!!!! Dat betekent, dat de X-as een Z-as is geworden (om het even simpel uit te leggen) en de Z-as een X-as. Dit komt doordat de rotatieformules op elkaar doorwerken. Dus je draait een punt om de X-as. Vervolgens draai je dat GEROTEERDE punt om de Y-as en daarna het resultaat daarvan om de Z-as. Hierdoor is het makkelijk in te zien dat de assen gaan wisselen (dit gebeurt dus niet werkelijk, maar effectievelijk is dat wat het makkelijkst uit te leggen is).
Ik snap ook wel wat je wilt. Je wilt dat de kubus telkens om de 'oude' X-as draait en de 'oude' Z (of Y, ik weet niet meer welke het was)-as. Om dit te realiseren, moet je gewoon simpelweg rekening houden met dit 'wisselen' van assen. Als je mij niet snapt, stuur me de FLA dan maar, dan pas ik het even voor je aan, zodat je waarschijnlijk het effect krijgt wat je wilde realiseren.
Oh ja, een simpele remedie -> reset de hoeken, wanneer de muis weer gaat bewegen ;)
TjOeNeR
%Europe/Berlin %719 %2005, 18:16
Jah, jij hebt dus door wat ik wilde maken :)
Eeeuhm, de FLA...
Is de functie ook goed? Want ik werk met SEPY en ik include alles.
En dit stukje code komt uit een class eigenlijk :)
De objecten tmp en rot zijn al gemaakt in de constructor...
function rotateXYZ (angx:Number, angy:Number, angz:Number):Object {
var sinx:Number = Math.sin (angx * rad);
var cosx:Number = Math.cos (angx * rad);
var siny:Number = Math.sin (angy * rad);
var cosy:Number = Math.cos (angy * rad);
var sinz:Number = Math.sin (angz * rad);
var cosz:Number = Math.cos (angz * rad);
//Rotate around X axis
tmp.y = (cosx * vec.y) - (sinx * vec.z);
tmp.z = (sinx * vec.y) + (cosx * vec.z);
//Rotate around Y axis
tmp.x = (siny * tmp.z) + (cosy * vec.x);
rot.z = (cosy * tmp.z) - (siny * vec.x);
//Rotate around Z axis
rot.x = (cosz * tmp.x) - (sinz * tmp.y);
rot.y = (sinz * tmp.x) + (cosz * tmp.y);
//Return values
return rot;
}
Srry, maar ik script in't Engels, dunno why, is er vanzelf gekomen...
TjOeNeR
%Europe/Berlin %477 %2005, 12:27
kH_ al iets gevonden?
kH_
%Europe/Berlin %481 %2005, 12:33
Sorry, ik ga er direct mee aan de gang, ik had het druk gisteren ;)
TjOeNeR
%Europe/Berlin %484 %2005, 12:37
thnx :) kh_ (10 tekens...)
kH_
%Europe/Berlin %620 %2005, 15:54
teringjantje, het is moeilijker dan ik dacht :)
Nou, ik heb na lang gespruts iets gemaakt wat maar gedeeltelijk werkt. Het probleem met de rotatie-formules is op 1 of ander manier het feit, dat soms 1 as niet afhankelijk is van de andere 2 assen. Dit is heel moeilijk uit te leggen, maar zo zit het wel. Als je eens zoekt op Google naar 'rotation around an arbitrary axis', dan zou je moeten uitkomen op matrix berekeningen waarvan je oren waarschijnlijk gaan flapperen als je niet erg wiskundig bent ingesteld (zelf ben ik experimenteel wiskundig ingesteld :)), maar ik geloof dat het daarmee wel lukt. Nou ja, je moet maar zien. Als attachment heb ik hierbij de FLA + SWF voor je van een voorbeeldje wat volgens mij een BEETJE lijkt op wat jij wilt.
Klik eerst met de muis om alles te resetten (klik in midden van het schermpje). Ga vervolgens met de muis iets naar links, zodat de kubus gaat draaien. Als je nu naar beneden gaat met de muis, dan klopt de X rotatie van de kubus wel (het komt overeen met wat je wilt). Bij sommige Y hoeken echter klopt er weer geen ruk van en dat komt door de niet afhankelijkheid van 2 assen op basis van een andere as. Nou ja, waarschijnlijk snap je dr geen ruk van, maar heb je een beetje een idee (hoop ik iig).
Oh ja, ik heb de volgorde van de rotaties aangepast om ervoor te zorgen dat er in het begin geen afhankelijkheidsprobleem is.
******, ik moet die 3D rotaties toch echt eens weer gaan uitpluizen. Ik weet wel dat dit probleem niet bestond toen ik rotaties uitvoerde via matrix berekeningen (trouwens een veel betere methode, doordat een matrix een formule template is eigenlijk, waardoor je een oneindig aantal complexe manipulaties op vectoren kunt uitvoeren. Echt de moeite waard om eens uit te gaan zoeken (in Direct3D doe je niet anders dan werken met matrices)).
Veel plezier ermee :confused:
Oh ja, hieronder ook nog ff de volledige ActionScript code (lijkt waarschijnlijk niet meer op wat jij had :)):
var tmp:Object=new Object();
var tmp2D:Object=new Object();
var rot:Object=new Object();
var vec:Object=new Object();
var angles:String="";
var xa:Number=0;
var ya:Number=0;
var za:Number=0;
var xd:Number=1;
var yd:Number=1;
var zd:Number=1;
var c1:String="Y";
var c2:String="X";
/*
Dit klopt niet hoor ;)
In jouw code ga je ervan uit dat een radiaal 0.017... is, MAAR
dat is niet zo. Een radiaal is 180/PI. Alleen jouw manier is wel
leuk, aangezien een vermenigvuldiging sneller is dan een deling en
dan moet je inderdaad 1/(180/Math.PI) doen. Leuk gevonden!
*/
var rad:Number=1/(180/Math.PI);
var box:Array=new Array();
var box3D:Array=new Array();
for(var i=0;i<8;i++)
{
box3D.push(new Object({x:0,y:0,z:0}));
}
box.push(new Object({x:-50,y:-50,z:-50}));
box.push(new Object({x:50,y:-50,z:-50}));
box.push(new Object({x:50,y:50,z:-50}));
box.push(new Object({x:-50,y:50,z:-50}));
box.push(new Object({x:-50,y:-50,z:50}));
box.push(new Object({x:50,y:-50,z:50}));
box.push(new Object({x:50,y:50,z:50}));
box.push(new Object({x:-50,y:50,z:50}));
createEmptyMovieClip("screen",1);
rotateXYZ=function(angx:Number, angy:Number, angz:Number):Object {
var sinx:Number = Math.sin (angx * rad);
var cosx:Number = Math.cos (angx * rad);
var siny:Number = Math.sin (angy * rad);
var cosy:Number = Math.cos (angy * rad);
var sinz:Number = Math.sin (angz * rad);
var cosz:Number = Math.cos (angz * rad);
//Rotate around Z axis
tmp.x = (cosz * vec.x) - (sinz * vec.y);
tmp.y = (sinz * vec.x) + (cosz * vec.y);
//Rotate around X axis
rot.y = (cosx * tmp.y) - (sinx * vec.z);
tmp.z = (sinx * tmp.y) + (cosx * vec.z);
tmp.y=rot.y;
//Rotate around Y axis
rot.x = (siny * tmp.z) + (cosy * tmp.x);
rot.z = (cosy * tmp.z) - (siny * tmp.x);
//Return values
return rot;
}
convert3D=function(point:Object):Object
{
//Ik moest even snel een 2D naar 3D conversie routine hebben, dus
//ik kwam hierop (had ik ooit al eens gebruikt).
tmp2D.x=500*(point.x/(point.z+300));
tmp2D.y=500*(point.y/(point.z+300));
tmp2D.x+=Stage.width/2;
tmp2D.y+=Stage.height/2;
return tmp2D;
}
drawBox=function()
{
screen.clear();
for(var i=0;i<8;i++)
{
vec.x=box[i].x;
vec.y=box[i].y;
vec.z=box[i].z;
rotateXYZ(xa,ya,za);
box3D[i].x=rot.x;
box3D[i].y=rot.y;
box3D[i].z=rot.z;
}
screen.lineStyle(2,0xff,100);
var pnt1:Object=new Object();
var pnt2:Object=new Object();
for(var i=0;i<4;i++)
{
pnt1.x=convert3D(box3D[i]).x;
pnt1.y=convert3D(box3D[i]).y;
if(i!=3)
{
pnt2.x=convert3D(box3D[i+1]).x;
pnt2.y=convert3D(box3D[i+1]).y;
}
else
{
pnt2.x=convert3D(box3D[0]).x;
pnt2.y=convert3D(box3D[0]).y;
}
screen.moveTo(pnt1.x,pnt1.y);
screen.lineTo(pnt2.x,pnt2.y);
}
for(var i=0;i<4;i++)
{
pnt1.x=convert3D(box3D[i+4]).x;
pnt1.y=convert3D(box3D[i+4]).y;
if(i!=3)
{
pnt2.x=convert3D(box3D[i+4+1]).x;
pnt2.y=convert3D(box3D[i+4+1]).y;
}
else
{
pnt2.x=convert3D(box3D[4]).x;
pnt2.y=convert3D(box3D[4]).y;
}
screen.moveTo(pnt1.x,pnt1.y);
screen.lineTo(pnt2.x,pnt2.y);
}
for(var i=0;i<4;i++)
{
pnt1.x=convert3D(box3D[i]).x;
pnt1.y=convert3D(box3D[i]).y;
if(i!=3)
{
pnt2.x=convert3D(box3D[i+4]).x;
pnt2.y=convert3D(box3D[i+4]).y;
}
else
{
pnt2.x=convert3D(box3D[7]).x;
pnt2.y=convert3D(box3D[7]).y;
}
screen.moveTo(pnt1.x,pnt1.y);
screen.lineTo(pnt2.x,pnt2.y);
}
delete pnt1;
delete pnt2;
}
onMouseDown=function()
{
xa=0;
ya=0;
za=0;
c1="Y";
c2="X";
}
onEnterFrame=function()
{
_root.angles=Math.round(xa)+":"+Math.round(ya)+":"+Math.round(za);
drawBox();
screen.lineStyle(1,0,100);
screen.moveTo(Stage.width/2,Stage.height/2);
screen.lineTo(_xmouse,_ymouse);
var dx:Number=Stage.width/2-_xmouse;
var dy:Number=Stage.height/2-_ymouse;
if(c1=="Y")
{
ya+=(dx/50)*yd;
if((ya>=45 && ya<=135) || (ya>=225 && ya<=315))
{
if(ya>=45 && ya<=135)
{
zd=-1;
}
if(ya>=225 && ya<=315)
{
zd=1;
}
c2="Z";
}
else
{
if(ya>315 || (ya<45 && ya>0))
{
xd=1;
}
if(ya>=135 && ya<=225)
{
xd=-1;
}
c2="X";
}
}
if(c2=="X")
{
xa-=(dy/50)*xd;
}
else if(c2=="Z")
{
za+=(dy/50)*zd;
}
if(xa>359)xa=0;
if(ya>359)ya=0;
if(za>359)za=0;
if(xa<0)xa=359;
if(ya<0)ya=359;
if(za<0)za=359;
}
TjOeNeR
%Europe/Berlin %657 %2005, 16:46
Ik heb de volledige code nog niet bekeken, ga ik direct eens doen...
Wat je zegt met die afhankelijkheid klopt wel :)
De X-As is de enigste die altijd juist gedaan wordt
De Y-As is afhankelijk van de X-As
De Z-As is afhankelijk van de X-As en de Y-As
Dat komt door de formules, je geeft de gewijzigde coördinaten mee aan de volgende formule.
Nu in deze gast zijn code, doe die iets helemaal anders
http://www.macromedia.com/devnet/mx/flash/articles/flash_3d.html
Maar ik gaan die van u eens nazien, en mijn ondervindingen neerplanten hier :)
EDIT://
Jouw code is wel nice, en dat Radiaal geval was idd speciaal daarvoor gedaan :)
Maar die blijft zo precies haperen af en toe...
Ik ben er nog niet juist uit hoe het komt...
kH_
%Europe/Berlin %699 %2005, 17:46
Dat voorbeeldje is inderdaad juist. Die werkt ook met matrices trouwens.
Het grote probleem met de formules zie je daar niet terug. Het stomme van het gebruik van die formules is het feit, dat ze eigenlijk niet lijken te kloppen. Ik zat zo voor mezelf even een voorwerp te draaien, waarbij het me opviel dat dit wisselen van assen helemaal niet hoort te gebeuren. Op 1 of andere manier roteert het coordinaten-systeem ook mee, natuurlijk wil je dat niet. Je wilt dat een object altijd beweegt om een vast coordinaten systeem, waarbij je het systeem zelf ook kunt manipuleren. Zelf heb ik het idee dat het in de transformatie van 3D naar 2D ligt en niet zozeer in de formules zelf (aangezien die toch echt wel juist zijn, dat is wiskundig aan te tonen). Als je kijkt in het voorbeeld van Chad Corbin, dan heeft hij het over destructieve transformaties. Hierbij wordt het coordinaten systeem van een object telkens mee getransformeerd in relatie tot het wereld coordinaten systeem. En DAT is nu juist het probleem met die formules.
Door gebruik te maken van matrix berekeningen wordt de dus een duidelijke scheiding gemaakt tussen het coordinaten systeem van een object zelf en het coordinaten systeem van de wereld.
Om dit verschil duidelijk te krijgen moet je eens denken aan een situatie waarin jij in een klein 2x2x2 hokje zit. Als jij nu omhoog springt, dan spring je naar de lucht toe, aangezien de grond naar de lucht toe wijst (de Up vector ;)). Als een of andere idioot nu echter het hokje 180 graden draait om de X-as en jij springt omhoog, dan val je dus naar beneden, aangezien de 'grond' van het hokje nu het plafond is geworden.
Welnu, het coordinaten systeem van het hokje is dan dus het 'wereld' coordinaten systeem en het systeem van jou zelf is het coordinaten systeem van het object zelf. Als je nu gebruik maakt van die rotatieformules dan gebeurt er het volgende, wanneer jij een object roteert:
- De persoon in het hokje wordt geroteerd
- Het hokje wordt geroteerd
Hierdoor komt het coordinaten systeem dus ineens anders te leggen. X kan bijvoorbeeld ineens Y zijn geworden e.d. Dit komt allemaal doordat de splitsing in coordinatensystemen niet is opgenomen binnen het gebruik van die formules. Om deze reden moet je gebruik maken van matrix berekeningen (het zal vast ook met formules kunnen, aangezien een matrix niets anders is dan een formule vertaald naar een 2D grid waarmee je op een vaste manier kunt rekenen, met het voordeel dat je een oneindig aantal matrices achter elkaar kunt knopen om de meest complexe manipulaties op vectoren uit te voeren).
Die Chad heeft mij dit laten inzien door het volgende te zeggen:
How these methods are different from other 3D engines
Many of the 3D engines floating around the web today rely on code that modifies the coordinate information of the 3D object with respect to the global coordinate system each time the code is executed, performing what I call a destructive transformation. The fact that destructive transformations operate this way may not seem like a big deal because they can create very good 3D effects. However, in certain situations, it is necessary to retain the original coordinate information of the objects.
Better methods exist that retain the original coordinate information of the 3D objects, called non-destructive transformations. These transformations are the corner stone around which many professional 3D modeling programs are based. They allow us to create 3D objects that we can scale, move and animate in the global coordinate system while being able to view the object from any angle. To perform these transformations, we have to use matrix mathematics, representing a significant break from the 3D Flash code that is out there.
To learn more about matrix mathematics, go to the next section of this tutorial.
Dus, ga matrices gebruiken. Is trouwens helemaal niet zo moeilijk hoor. De projectie van 3D naar 2D is trouwens wel leuk. Hierbij wordt het coordinaten systeem van de wereld dusdanig verdraait, dat de Z-as haaks op je beeldscherm komt te staan. Op die manier kun je de Z coordinaat verwaarlozen. Mooi he? Om nu echter perspectief te zien wordt het wereldje geprojecteerd in een soort van kubische trechter (een kubus die steeds minder breed en minder hoog wordt, naarmate de diepte toeneemt). Je kunt je voorstellen, iets wat normaal in een kubus leeft en vervolgens wordt geprojecteerd in een kubische trechter, tja...daarvan gaan de coordinaten simpelweg afbuigen :)
Nou...veel plezier er maar weer mee dan.
vBulletin® v3.8.1, Copyright ©2000-2012, Jelsoft Enterprises Ltd.