From 1ecd803e87119c0344b91798792130155a82859c Mon Sep 17 00:00:00 2001
From: Teravus Ovares
Date: Fri, 23 Nov 2007 05:56:35 +0000
Subject: * added some functions for use in raytracing. They're kind of crappy
now, so they only display 'guesses' on the console when you rez a prim. * any
math gurus who'd like to improve rezzing need only to make the raytracer in
SceneObjectPart work :D
---
OpenSim/Region/Environment/Scenes/EntityBase.cs | 25 +++++++
OpenSim/Region/Environment/Scenes/InnerScene.cs | 27 +++++++
OpenSim/Region/Environment/Scenes/Scene.cs | 44 +++++++++++
.../Region/Environment/Scenes/SceneObjectGroup.cs | 38 ++++++++++
.../Region/Environment/Scenes/SceneObjectPart.cs | 85 ++++++++++++++++++++++
OpenSim/Region/Environment/Scenes/ScenePresence.cs | 5 ++
6 files changed, 224 insertions(+)
(limited to 'OpenSim/Region/Environment/Scenes')
diff --git a/OpenSim/Region/Environment/Scenes/EntityBase.cs b/OpenSim/Region/Environment/Scenes/EntityBase.cs
index 1c21159..94e2337 100644
--- a/OpenSim/Region/Environment/Scenes/EntityBase.cs
+++ b/OpenSim/Region/Environment/Scenes/EntityBase.cs
@@ -145,6 +145,31 @@ namespace OpenSim.Region.Environment.Scenes
return (EntityBase) MemberwiseClone();
}
+
+
public abstract void SetText(string text, Vector3 color, double alpha);
}
+
+ //Nested Classes
+ public class EntityIntersection
+ {
+ public Vector3 ipoint = new Vector3(0, 0, 0);
+ public float normal = 0;
+ public bool HitTF = false;
+ public SceneObjectPart obj;
+ public float distance = 0;
+
+ public EntityIntersection()
+ {
+
+
+ }
+ public EntityIntersection(Vector3 _ipoint, float _normal, bool _HitTF)
+ {
+ ipoint = _ipoint;
+ normal = _normal;
+ HitTF = _HitTF;
+ }
+
+ }
}
\ No newline at end of file
diff --git a/OpenSim/Region/Environment/Scenes/InnerScene.cs b/OpenSim/Region/Environment/Scenes/InnerScene.cs
index 38a8a06..8f7cbee 100644
--- a/OpenSim/Region/Environment/Scenes/InnerScene.cs
+++ b/OpenSim/Region/Environment/Scenes/InnerScene.cs
@@ -253,6 +253,33 @@ namespace OpenSim.Region.Environment.Scenes
return null;
}
+ public EntityIntersection GetClosestIntersectingPrim(Ray hray)
+ {
+ // Primitive Ray Tracing
+ bool gothit = false;
+ float closestDistance = 280f;
+ EntityIntersection returnResult = new EntityIntersection();
+ foreach (EntityBase ent in Entities.Values)
+ {
+ if (ent is SceneObjectGroup)
+ {
+ SceneObjectGroup reportingG = (SceneObjectGroup)ent;
+ EntityIntersection result = reportingG.testIntersection(hray);
+ if (result.HitTF)
+ {
+ if (result.distance < closestDistance)
+ {
+ gothit = true;
+ closestDistance = result.distance;
+ returnResult = result;
+ }
+ }
+ }
+
+ }
+ return returnResult;
+ }
+
public SceneObjectPart GetSceneObjectPart(uint localID)
{
SceneObjectGroup group = GetGroupByPrim(localID);
diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs
index 90306f2..ef96e3d 100644
--- a/OpenSim/Region/Environment/Scenes/Scene.cs
+++ b/OpenSim/Region/Environment/Scenes/Scene.cs
@@ -635,8 +635,52 @@ namespace OpenSim.Region.Environment.Scenes
///
public void AddNewPrim(LLUUID ownerID, LLVector3 pos, LLQuaternion rot, PrimitiveBaseShape shape)
{
+
+ // What we're *supposed* to do is raytrace from the camera position given by the client to the nearest collision
+ // in the direction the client supplies (the ground level that we clicked)
+ // This function is pretty crappy right now.. so we're not affecting where the newly rezzed objects go
+ // Test it if you like. The console will write where it guesses a collision took place. if it thinks one did.
+ // It's wrong many times though.
+
if (PermissionsMngr.CanRezObject(ownerID, pos))
{
+ Vector3 CameraPosition = ((ScenePresence)GetScenePresence(ownerID)).CameraPosition;
+ Vector3 rayEnd = new Vector3(pos.X, pos.Y, pos.Z);
+
+ float raydistance = m_innerScene.Vector3Distance(CameraPosition, rayEnd);
+
+ Vector3 rayDirection = new Vector3(rayEnd.x / raydistance, rayEnd.y / raydistance, rayEnd.z / raydistance);
+
+ Ray rezRay = new Ray(CameraPosition, rayDirection);
+
+
+ Vector3 RezDirectionFromCamera = rezRay.Direction;
+
+ EntityIntersection rayTracing = m_innerScene.GetClosestIntersectingPrim(rezRay);
+
+ if (rayTracing.HitTF)
+ {
+ // We raytraced and found a prim in the way of the ground.. so
+ // We will rez the object somewhere close to the prim. Better math needed. This is a Stub
+ //Vector3 Newpos = new Vector3(rayTracing.obj.AbsolutePosition.X,rayTracing.obj.AbsolutePosition.Y,rayTracing.obj.AbsolutePosition.Z);
+ Vector3 Newpos = rayTracing.ipoint;
+ Vector3 NewScale = new Vector3(rayTracing.obj.Scale.X,rayTracing.obj.Scale.Y,rayTracing.obj.Scale.Z);
+
+ Quaternion ParentRot = rayTracing.obj.ParentGroup.Rotation;
+ //Quaternion ParentRot = new Quaternion(primParentRot.W,primParentRot.X,primParentRot.Y,primParentRot.Z);
+
+ LLQuaternion primLocalRot = rayTracing.obj.RotationOffset;
+ Quaternion LocalRot = new Quaternion(primLocalRot.W,primLocalRot.X,primLocalRot.Y,primLocalRot.Z);
+
+ Quaternion NewRot = LocalRot * ParentRot;
+
+ Vector3 RezPoint = Newpos;
+
+ MainLog.Instance.Verbose("REZINFO","Possible Rez Point:" + RezPoint.ToString());
+ //pos = new LLVector3(RezPoint.x, RezPoint.y, RezPoint.z);
+
+ }
+
SceneObjectGroup sceneOb =
new SceneObjectGroup(this, m_regionHandle, ownerID, PrimIDAllocate(), pos, rot, shape);
AddEntity(sceneOb);
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
index 474d434..45581c5 100644
--- a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs
@@ -353,6 +353,44 @@ namespace OpenSim.Region.Environment.Scenes
}
}
+ public EntityIntersection testIntersection(Ray hRay)
+ {
+ EntityIntersection returnresult = new EntityIntersection();
+ bool gothit = false;
+ foreach (SceneObjectPart part in m_parts.Values)
+ {
+ SceneObjectPart returnThisPart = null;
+ Vector3 partPosition = new Vector3(part.AbsolutePosition.X,part.AbsolutePosition.Y,part.AbsolutePosition.Z);
+ Quaternion parentrotation = new Quaternion(GroupRotation.W,GroupRotation.X,GroupRotation.Y,GroupRotation.Z);
+ EntityIntersection inter = part.testIntersection(hRay,parentrotation);
+
+ float idist = 256f;
+
+
+
+
+ if (inter.HitTF) {
+ // We need to find the closest prim to return to the testcaller along the ray
+ if (inter.distance < idist) {
+
+ idist = inter.distance;
+ returnresult.HitTF = true;
+ returnresult.ipoint = inter.ipoint;
+ returnresult.obj = part;
+ returnresult.normal = inter.normal;
+ returnresult.distance = inter.distance;
+ gothit = true;
+ }
+ }
+
+
+ }
+ return returnresult;
+
+ }
+
+
+
///
///
///
diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
index 7bab3b6..e68632b 100644
--- a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs
@@ -535,6 +535,91 @@ namespace OpenSim.Region.Environment.Scenes
serializer.Serialize(xmlWriter, this);
}
+ public EntityIntersection testIntersection(Ray iray, Quaternion parentrot)
+ {
+
+ //Sphere dummysphere = new Sphere();
+
+ EntityIntersection returnresult = new EntityIntersection();
+ Vector3 vAbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z);
+ Vector3 vScale = new Vector3(Scale.X, Scale.Y, Scale.Z);
+ Quaternion qRotation = new Quaternion(RotationOffset.W, RotationOffset.X, RotationOffset.Y, RotationOffset.Z);
+
+
+
+ Quaternion worldRotation = (qRotation * parentrot);
+ Matrix3 worldRotM = worldRotation.ToRotationMatrix();
+
+
+
+ Vector3 rOrigin = iray.Origin;
+ Vector3 rDirection = iray.Direction;
+
+
+
+ Vector3 r2ndDirection = rDirection * rDirection;
+
+ float itestPart1 = r2ndDirection.x + r2ndDirection.y + r2ndDirection.z;
+
+ Vector3 tmVal2 = rOrigin - vAbsolutePosition;
+
+ Vector3 r2Direction = rDirection * 2.0f;
+ Vector3 tmVal3 = r2Direction * tmVal2;
+
+ float itestPart2 = tmVal3.x + tmVal3.y + tmVal3.z;
+
+ Vector3 tmVal4 = rOrigin * rOrigin;
+ Vector3 tmVal5 = vAbsolutePosition * vAbsolutePosition;
+
+ Vector3 tmVal6 = vAbsolutePosition * rOrigin;
+
+ float radius = 0f;
+ if (vScale.x > radius)
+ radius = vScale.x;
+ if (vScale.y > radius)
+ radius = vScale.y;
+ if (vScale.z > radius)
+ radius = vScale.z;
+
+ //radius = radius;
+
+ float itestPart3 = tmVal4.x + tmVal4.y + tmVal4.z + tmVal5.x + tmVal5.y + tmVal5.z -(2.0f * (tmVal6.x + tmVal6.y + tmVal6.z + (radius * radius)));
+
+ // Yuk Quadradrics
+ float rootsqr = (itestPart2 * itestPart2) - (4.0f * itestPart1 * itestPart3);
+ if (rootsqr < 0.0f)
+ {
+
+ return returnresult;
+ }
+ float root = ((-itestPart2) - (float)Math.Sqrt((double)rootsqr)) / (itestPart1 * 2.0f);
+
+ if (root < 0.0f)
+ {
+ // perform second quadratic root solution
+ root = ((-itestPart2) + (float)Math.Sqrt((double)rootsqr)) / (itestPart1 * 2.0f);
+
+ // is there any intersection?
+ if (root < 0.0f)
+ {
+
+ return returnresult;
+ }
+ }
+
+ Vector3 ipoint = new Vector3(iray.Origin.x + (iray.Direction.x * root),iray.Origin.y + (iray.Direction.y * root),iray.Origin.z + (iray.Direction.z * root));
+
+ returnresult.HitTF = true;
+ returnresult.ipoint = ipoint;
+ Vector3 normalpart = ipoint-vAbsolutePosition;
+ returnresult.normal = normalpart.Normalize();
+ returnresult.distance = ParentGroup.m_scene.m_innerScene.Vector3Distance(iray.Origin, ipoint);
+
+ return returnresult;
+ }
+
+
+
///
///
///
diff --git a/OpenSim/Region/Environment/Scenes/ScenePresence.cs b/OpenSim/Region/Environment/Scenes/ScenePresence.cs
index 3929f0f..850d3a4 100644
--- a/OpenSim/Region/Environment/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Environment/Scenes/ScenePresence.cs
@@ -147,6 +147,11 @@ namespace OpenSim.Region.Environment.Scenes
get { return m_regionHandle; }
}
+ public Vector3 CameraPosition
+ {
+ get { return m_CameraCenter; }
+ }
+
private readonly string m_firstname;
public string Firstname
--
cgit v1.1