Seite 1 von 1

[Stage3D] Picking / Ray Probleme

Verfasst: 15.07.2012, 14:43
von Stimpy
Hallo Ihr lieben ZFX'ler,

nach diversen Google Suchen und Fragen auf anderen Plattform konnte mir bisher nirgendwo geholfen werden und auch ich bin noch nicht auf die Lösung gekommen. Daher frage ich auch hier noch einmal nach und hoffe - Nein bete sogar das mir jemand helfen kann.

Es geht um Picking über ein Ray, dass ist in Stage ja nicht anders als in OpenGL oder DirectX - Also habe ich mir ein OpenGL Code genommen und umgeschrieben für Stage3D/Flash, das sieht nun so aus:

Code: Alles auswählen

var mX:Number = -1 + (p.x / winSize.x)  * 2;
        var mY:Number =  1 - (p.y / winSize.y) * 2;
     
        var farPos:Vector3D = new Vector3D( mX, mY,  1.0, 1.0 );
        var nearPos:Vector3D = new Vector3D( mX, mY, 0.0, 1.0 );
         
        var mt:Matrix3D = new Matrix3D();
        mt.append(getProjection());
        mt.append(getView());
        mt.invert();
         
        nearPos = mt.transformVector(nearPos);
        farPos = mt.transformVector(farPos);
         
        nearPos.scaleBy(1.0 / nearPos.w);
        farPos.scaleBy(1.0 / farPos.w);
         
        var Dir:Vector3D = farPos.subtract(nearPos);
        Dir.normalize();
 
        return new CRay(nearPos, Dir);
So habe ich den Code umgebaut. Ich treffe jedoch nichts mit meinem Ray oder immer das falsche Objekt.

Jetzt habe ich aus Verzweiflung einfach mit den Werten rumgespielt und festgestellt das wenn ich folgendes mache:

Code: Alles auswählen

return new CRay(nearPos.subtract(position.add(Dir))


Das Ray genau trifft, auch die Position zurückgerechnet stimmt usw. - Alles perfekt - Bis ich die Kamera bewege oder Rotiere, dann treffe ich gar nix mehr. Was wohl daran liegt das ich die Camera da mnit reingnommen habe(position = camera position).

Hat hier jemand eine Idee wie ich den original code verändern muss damit das ganze läuft? Ich bin dem Wahnsinn schon nahe :(

Vielen Dank im Vorraus

Re: [Stage3D] Picking / Ray Probleme

Verfasst: 15.07.2012, 15:27
von Artificial Mind
ist nearPos nicht new Vector3D( mX, mY, -1.0, 1.0 );?
In den Normalized Device Coordinates von OpenGL gehen X, Y und Z jedenfalls alle drei von -1 bis 1.

Ich denke du hast bereits geprüft, dass p.x von 0 bis winSize.x - 1 geht (also relativ und in Pixeln angegeben ist), richtig?

Bei der Matrix-Klasse bin ich mir nicht sicher, ob Stage da die gleiche Reihenfolge wie OpenGL hat. Generell ist Vektorarithmetik ohne Operatorüberladung hässlich >.<

Re: [Stage3D] Picking / Ray Probleme

Verfasst: 15.07.2012, 15:55
von Stimpy
Hi,

erst einmal vielen Dank für den Versuch zu helfen - Ich bin hier echt verzweifelt :|

Also nearPos habe ich auf -1 geändert - Hat kein Effekt. Aber ich bin mir nicht ganz sicher was du meintest mit relativ und in pixeln? p ist der Mauskoordinate wobei das Orgin oben links ist, soweit ich das verstehe also ja relativ und in pixeln.

Er bekommt also z.B.

737,559 | 1024,768 (P.X,P.Y | WinSize.X,WinSize.Y)

Re: [Stage3D] Picking / Ray Probleme

Verfasst: 15.07.2012, 16:01
von Artificial Mind
Ja, das meinte ich mit relativ und in Pixeln.
Stimpy hat geschrieben:

Code: Alles auswählen

return new CRay(nearPos.subtract(position.add(Dir))
Fehlt da nicht ein Argument?

Kannst du sonst noch mal einen Ausschnitt aus dem Code zeigen, wo die die Strahlen mit den Objekten schneidest?

Re: [Stage3D] Picking / Ray Probleme

Verfasst: 15.07.2012, 16:04
von Stimpy
Also die Argumente sind das Orgin des Rays und die Direction.

Das sind einfach zwei Vektoren in der Klasse:

Code: Alles auswählen

public function CRay(orgin:Vector3D,dir:Vector3D) 
		{
			ray_origin = orgin;
			ray_dir = dir;
		}
Die eigentliche Funktion checkt dann mit einer AABB:

Code: Alles auswählen

	public function intersectRayAABox(ray:CRay, min:CVertex,max:CVertex, tnear:int, tfar:int,t:Number):Boolean
		{
			// r.dir is unit direction vector of ray
			var dirfrac:Vector3D = new Vector3D();
			dirfrac.x = 1.0 / ray.ray_dir.x;
			dirfrac.y = 1.0 / ray.ray_dir.y;
			dirfrac.z = 1.0 / ray.ray_dir.z;
			// lb is the corner of AABB with minimal coordinates - left bottom, rt is maximal corner
			// r.org is origin of ray
			var t1:Number = (min.x - ray.ray_origin.x)*dirfrac.x;
			var t2:Number = (max.x - ray.ray_origin.x)*dirfrac.x;
			var t3:Number = (min.y - ray.ray_origin.y)*dirfrac.y;
			var t4:Number = (max.y - ray.ray_origin.y)*dirfrac.y;
			var t5:Number = (min.z - ray.ray_origin.z)*dirfrac.z;
			var t6:Number = (max.z - ray.ray_origin.z)*dirfrac.z;

			var tmin:Number = Math.max(Math.max(Math.min(t1, t2), Math.min(t3, t4)), Math.min(t5, t6));
			var tmax:Number = Math.min(Math.min(Math.max(t1, t2), Math.max(t3, t4)), Math.max(t5, t6));
	
			// if tmax < 0, ray (line) is intersecting AABB, but whole AABB is behing us
			if (tmax < 0)
			{
				t = tmax;
				return false;
			}

			// if tmin > tmax, ray doesn't intersect AABB
			if (tmin > tmax)
			{
				t = tmax;
				return false;
			}

			t = tmin;
			return true;
		}

Re: [Stage3D] Picking / Ray Probleme

Verfasst: 15.07.2012, 16:20
von Artificial Mind
Artificial Mind hat geschrieben:
Stimpy hat geschrieben:

Code: Alles auswählen

return new CRay(nearPos.subtract(position.add(Dir))
Fehlt da nicht ein Argument?
CRay braucht 2 Arguemnte, ich sehe hier aber nur eines (oder bin ich blind?).

Re: [Stage3D] Picking / Ray Probleme

Verfasst: 15.07.2012, 16:24
von Stimpy
Achso, sorry - Da muss mir beim reinkopieren ein Fehler unterlaufen sein, es ist im Code natürlich:

Code: Alles auswählen

return new CRay(nearPos, Dir);
Beziehungsweise:

Code: Alles auswählen

return new CRay(nearPos.subtract(position.add(Dir)), Dir);
Letzteres klappt ja sogar,solange man die Kamera nicht bewegt...

Re: [Stage3D] Picking / Ray Probleme

Verfasst: 16.07.2012, 10:50
von Stimpy
Ich habe es am Sonntag nun doch irgendwie geschafft alleine ;)

Falls es hier noch den ein oder anderen Stage'er gibt, hier der fertige funktionierende Code:

Code: Alles auswählen

	public function ScreenRayToWorld(p:Point, winSize:Point):CRay
		{
			var NEAR:Number = 0.1;
			var FAR:Number = 5000;
			var ASPECT:Number =  winSize.y / winSize.x;
			var WIDTH_DIV_2:int = winSize.x * 0.5;
			
			var dx:Number=Math.tan((45 * Math.PI / 180)*0.5)*(p.x / WIDTH_DIV_2 - 1.0) / ASPECT;
			var dy:Number=Math.tan((45 * Math.PI / 180)*0.5)*(1.0-p.y/(winSize.y * 0.5));
			
			var mt:Matrix3D = new Matrix3D();
			mt.append(getView());
			mt.invert();

			var p1:Vector3D=new Vector3D(dx*NEAR,dy*NEAR,NEAR,1);
			var p2:Vector3D = new Vector3D(dx * FAR, dy * FAR, FAR,1);
			
			p1 = mt.transformVector(p1);
			p2 = mt.transformVector(p2);
			
			var dir:Vector3D = new Vector3D();
			dir = p2.subtract(p1);

			return new CRay(p1,dir);
		}
Grüße und bis bald

Stimpy