private PhysicsConvexShape ConvertToMesh(PrimitivePhysicsShapeType physicsShape, ObjectPart.PrimitiveShape shape) { PhysicsConvexShape convexShape = null; bool hasHullList = false; if (shape.Type == PrimitiveShapeType.Sculpt && shape.SculptType == PrimitiveSculptType.Mesh) { var m = new LLMesh(m_AssetService[shape.SculptMap]); if (physicsShape == PrimitivePhysicsShapeType.Convex) { #if DEBUG m_Log.DebugFormat("Selected convex of {0}/{1}/{2}", shape.Type, shape.SculptType, shape.SculptMap); #endif if (m.HasConvexPhysics()) { try { #if DEBUG m_Log.DebugFormat("Using convex of {0}/{1}/{2}", shape.Type, shape.SculptType, shape.SculptMap); #endif convexShape = m.GetConvexPhysics(false); hasHullList = convexShape.HasHullList; return(convexShape); } catch (NoSuchMeshDataException) { /* no shape */ #if DEBUG m_Log.DebugFormat("No convex in asset of {0}/{1}/{2}", shape.Type, shape.SculptType, shape.SculptMap); #endif } catch (Exception e) { m_Log.Warn($"Failed to get convex data of {shape.SculptType} {shape.SculptMap}", e); } } #if DEBUG else { m_Log.DebugFormat("No convex shape in {0}/{1}/{2}", shape.Type, shape.SculptType, shape.SculptMap); } #endif if (convexShape == null) { #if DEBUG m_Log.DebugFormat("Using decompose to single convex for {0}/{1}/{2}", shape.Type, shape.SculptType, shape.SculptMap); #endif MeshLOD lod = m.GetLOD(LLMesh.LodLevel.LOD3); lod.Optimize(); convexShape = DecomposeConvex(lod, true); } } else { #if DEBUG m_Log.DebugFormat("Selected detailed physics of {0}/{1}/{2}", shape.Type, shape.SculptType, shape.SculptMap); #endif if (m.HasLOD(LLMesh.LodLevel.Physics)) { /* check for physics mesh before giving out the single hull */ #if DEBUG m_Log.DebugFormat("Using detailed physics of {0}/{1}/{2}", shape.Type, shape.SculptType, shape.SculptMap); #endif MeshLOD lod = m.GetLOD(LLMesh.LodLevel.Physics); lod.Optimize(); convexShape = DecomposeConvex(lod); } else if (m.HasConvexPhysics()) { #if DEBUG m_Log.DebugFormat("Using convex of {0}/{1}/{2}", shape.Type, shape.SculptType, shape.SculptMap); #endif try { convexShape = m.GetConvexPhysics(true); hasHullList = convexShape.HasHullList; } catch (NoSuchMeshDataException) { /* no shape */ #if DEBUG m_Log.DebugFormat("No suitable convex in asset of {0}/{1}/{2}", shape.Type, shape.SculptType, shape.SculptMap); #endif } catch (Exception e) { m_Log.Warn($"Failed to get convex data of {shape.Type}/{shape.SculptType}/{shape.SculptMap}", e); } if (convexShape == null) { /* this way we keep convex hull type functional by having it only get active on PrimitivePhysicsShapeType.Prim */ #if DEBUG m_Log.DebugFormat("Using decompose to convex for {0}/{1}/{2}", shape.Type, shape.SculptType, shape.SculptMap); #endif MeshLOD lod = m.GetLOD(LLMesh.LodLevel.LOD3); lod.Optimize(); convexShape = DecomposeConvex(lod); } } } } else { #if DEBUG m_Log.DebugFormat("Using decompose to convex for {0}/{1}/{2}", shape.Type, shape.SculptType, shape.SculptMap); #endif MeshLOD m = shape.ToMesh(m_AssetService); m.Optimize(); convexShape = DecomposeConvex(m, physicsShape == PrimitivePhysicsShapeType.Convex); } return(convexShape); }
private void GetObjectMatches(RayData ray, RayTestHitFlags flags, List <RayResult> results) { foreach (ObjectGroup grp in m_Scene.ObjectGroups) { if (grp.IsAttached) { /* ignore attachments */ continue; } /* flag checks are cheap so do those first */ if (((flags & RayTestHitFlags.NonPhantom) != 0 && !grp.IsPhantom) || ((flags & RayTestHitFlags.Phantom) != 0 && grp.IsPhantom) || ((flags & RayTestHitFlags.NonPhysical) != 0 && !grp.IsPhysics) || ((flags & RayTestHitFlags.Physical) != 0 && grp.IsPhysics)) { /* found a flag match */ } else { continue; } BoundingBox bbox; grp.GetBoundingBox(out bbox); bbox.CenterOffset = grp.GlobalPosition; bbox.Size *= grp.GlobalRotation; bbox.Size = bbox.Size.ComponentMax(-bbox.Size); double distance = IntersectBox(ray, ref bbox); if (distance < 0) { /* only process if linkset bounding box is hit */ continue; } foreach (ObjectPart part in grp.ValuesByKey1) { part.GetBoundingBox(out bbox); distance = IntersectBox(ray, ref bbox); if (distance < 0) { /* skip if not hit */ continue; } var res = new RayResult { ObjectId = grp.ID, PartId = part.ID }; /* calculate actual HitPoint and HitNormal */ ObjectPart.PrimitiveShape shape = part.Shape; MeshLOD lod = null; if (shape.Type == PrimitiveShapeType.Sculpt && shape.SculptType == PrimitiveSculptType.Mesh) { var m = new LLMesh(m_Scene.AssetService[shape.SculptMap]); foreach (LLMesh.LodLevel level in LodOrder) { if (m.HasLOD(level)) { lod = m.GetLOD(level); break; } } } else { lod = shape.ToMesh(m_Scene.AssetService); } if (lod != null) { lod.Optimize(); Vector3 normal; foreach (Triangle tri in lod.Triangles) { double dist = IntersectTri(ray, lod.Vertices[tri.Vertex1], lod.Vertices[tri.Vertex2], lod.Vertices[tri.Vertex3], out normal); if (dist >= 0) { res.HitNormalWorld = normal; res.HitPointWorld = ray.Origin + ray.Direction * dist; results.Add(res); break; } } } } } }