From 1ecd803e87119c0344b91798792130155a82859c Mon Sep 17 00:00:00 2001 From: Teravus Ovares Date: Fri, 23 Nov 2007 05:56:35 +0000 Subject: [PATCH] * 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 --- .../Region/Environment/Scenes/EntityBase.cs | 25 ++++++ .../Region/Environment/Scenes/InnerScene.cs | 27 ++++++ OpenSim/Region/Environment/Scenes/Scene.cs | 44 ++++++++++ .../Environment/Scenes/SceneObjectGroup.cs | 38 +++++++++ .../Environment/Scenes/SceneObjectPart.cs | 85 +++++++++++++++++++ .../Environment/Scenes/ScenePresence.cs | 5 ++ 6 files changed, 224 insertions(+) diff --git a/OpenSim/Region/Environment/Scenes/EntityBase.cs b/OpenSim/Region/Environment/Scenes/EntityBase.cs index 1c21159587..94e23376ee 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 38a8a06b98..8f7cbee6fe 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 90306f2337..ef96e3d428 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 474d434aa9..45581c56bb 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 7bab3b6cbd..e68632b933 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 3929f0f592..850d3a4cee 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