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);
        }
Esempio n. 2
0
        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;
                            }
                        }
                    }
                }
            }
        }