Triangle Intersection: Unterschied zwischen den Versionen

Aus Das Sopra Wiki
Dietsch (Diskussion | Beiträge)
Keine Bearbeitungszusammenfassung
Florian (Diskussion | Beiträge)
Keine Bearbeitungszusammenfassung
 
(5 dazwischenliegende Versionen von 2 Benutzern werden nicht angezeigt)
Zeile 1: Zeile 1:
{{Stub}}
{{review}}


__TOC__
__TOC__
Zeile 107: Zeile 107:
</source>
</source>


Damit die Methode möglichst performant ist wurde die Anzahl an Methodenaufrufen durch Inlining möglichst minimiert und es werden [[Parameterübergabe#Call_by_Reference | Call by Reference]] und [[Parameterübergabe#Rückgabeparameter | Rückgabeparameter]] verwendet. Diese Methode muss für jedes Triangle eines Meshes aufgerufen werden, also sogar schon bei Modellen mit wenigen Hundert Polygonen sehr oft, daher können diese Optimierungen einen bedeutenden Performance Gewinn bringen.
Damit die Methode möglichst performant ist wurde die Anzahl an Methodenaufrufen durch Inlining möglichst minimiert und es werden [[Parameterübergabe#Call_by_Reference | Call by Reference]] und [[Parameterübergabe#Rückgabeparameter | Rückgabeparameter]] verwendet. Diese Methode muss für jedes Triangle eines Meshes aufgerufen werden, also sogar schon bei Modellen mit wenigen Hundert Polygonen sehr oft, daher können diese Optimierungen einen bedeutenden Geschwindigkeits-Gewinn bringen. [[Kategorie:Code-Beispiele]]


== Auslesen des Meshs eines Models ==
== Auslesen des Meshs eines Models ==
Zeile 164: Zeile 164:
     //get the vertex data
     //get the vertex data
     this.vertices = new Vector3[meshPart.NumVertices];
     this.vertices = new Vector3[meshPart.NumVertices];
     meshPart.VertexBuffer.GetData<Vector3>(meshPart.VertexOffset, this.vertices, 0, meshPart.NumVertices, meshPart.VertexBuffer.VertexDeclaration.VertexStride);
     meshPart.VertexBuffer.GetData<Vector3>(meshPart.VertexOffset * meshPart.VertexBuffer.VertexDeclaration.VertexStride, this.vertices, 0, meshPart.NumVertices, meshPart.VertexBuffer.VertexDeclaration.VertexStride);
     //transform the vertex data
     //transform the vertex data
     for (int i = 0; i < this.vertices.Length; ++i)
     for (int i = 0; i < this.vertices.Length; ++i)
Zeile 275: Zeile 275:
Ray objectRay = new Ray();
Ray objectRay = new Ray();
//1) calculate the inverse world matrix of the object
//1) calculate the inverse world matrix of the object
Matrix worldMatrix = object.WorldMatrix; //(the world matrix is just the combined scale, orientation and translation matrix)
Matrix worldMatrix = object.WorldMatrix; //(the world matrix is just the combined scale, orientation and translation matrix of the object)
Matrix objectSpaceMatrix;
Matrix objectSpaceMatrix;
Matrix.Invert(ref worldMatrix, out objectSpaceMatrix);
Matrix.Invert(ref worldMatrix, out objectSpaceMatrix);
Zeile 285: Zeile 285:


Das Codebeispiel erzeugt mit <tt>objectRay</tt> einen neuen Strahl welcher dem originalen Strahl im Object Space des Models entspricht. Dieser kann dann mit der <tt>Intersect()</tt>-Methode der <tt>MeshTriangleData</tt> Klasse verwendet werden.
Das Codebeispiel erzeugt mit <tt>objectRay</tt> einen neuen Strahl welcher dem originalen Strahl im Object Space des Models entspricht. Dieser kann dann mit der <tt>Intersect()</tt>-Methode der <tt>MeshTriangleData</tt> Klasse verwendet werden.
==== Rücktransformation der Ergebnisdistanz in den World Space ====
Da der Strahl zur Schnittpunktberechnung in den Object Space des entsprechenden Models transformiert wurde erhält man als Ergebnis der <tt>Intersect()</tt>-Methode der <tt>MeshTriangleData</tt> Klasse entsprechend die Distanz auf dem Strahl ebenfalls im Object Space des Modells! Damit man diese nun mit den Schnittdistanzen von anderen Modellen vergleichen kann um den nahsten Schnittpunkt für das Ray Tracing zu bestimmen muss man die erhaltenen Distanzen für jedes einzelne Modell (Innerhalb eines Modells, also für die einzelnen Meshes und Mesh Parts, kann man natürlich die Distanzen im Object Space vergleichen da sich diese alle im selben Object Space befinden) vorher wieder zurück in den World Space transformieren. Dies kann man wie folgt implementieren:
<source lang="CSharp">
//we have
GameObject object; //some object which uses a model which we want to check for a ray intersection
Ray ray; //the intersecting ray, as usual in the world space
Ray objectRay; //the intersecting ray in the object space of the model
float? result; //the distance of the intersection point on the ray in the object space of the model
//we will get
float? worldResult = null; //the distance of the intersection point on the ray in world space or null if there was no intersection
if (result.HasValue)
{
  //calculate the intersection point in the object space
  Vector3 intersectionPoint = objectRay.Position + objectRay.Direction * result.Value;
  //transform the intersection point into world space
  Vector3.Transform(ref intersectionPoint, ref object.worldMatrix, out intersectionPoint); //(the world matrix is just the combined scale, orientation  and translation matrix of the object)
  //intersectionPoint now contains the intersection point of the ray and the object in world space, you might want to return it if you need it at some time
  //calculate the distance from the ray position to the intersection point as the distance in world space
  Vector3 rayOriginToIntersectionPoint = intersectionPoint - ray.Position;
  worldResult = rayOriginToIntersectionPoint.Length();
}
</source>
Die so berechnete Entfernung im World Space kann dann ganz normal unter den einzelnen Modellen verglichen werden um den nahsten Schnittpunkt und damit das vom Strahl getroffende Objekt zu bestimmen. Nebenbei erhält man auch den Schnittpunkt des Strahls und des Objekts im World Space und kann diesen direkt weiterverwenden ohne ihn später erneut aus der Distanz berechnen zu müssen um z.B. einen Effekt am Auftreffpunkt zu erzeugen.


[[Kategorie:Code-Beispiele]][[Kategorie:Tutorials]]
[[Kategorie:Code-Beispiele]][[Kategorie:Tutorials]]
[[Kategorie:MS02]]
[[Kategorie:MS03]]
[[Kategorie:MS04]]