diff options
Diffstat (limited to 'OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs')
-rw-r--r-- | OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | 163 |
1 files changed, 98 insertions, 65 deletions
diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs index 80c1277..0a4ebe4 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs | |||
@@ -704,6 +704,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
704 | if (m_isphysical) | 704 | if (m_isphysical) |
705 | m_targetSpace = _parent_scene.space; | 705 | m_targetSpace = _parent_scene.space; |
706 | 706 | ||
707 | _triMeshData = IntPtr.Zero; | ||
708 | |||
707 | m_primName = primName; | 709 | m_primName = primName; |
708 | m_taintserial = null; | 710 | m_taintserial = null; |
709 | m_taintadd = true; | 711 | m_taintadd = true; |
@@ -773,6 +775,8 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
773 | m_targetSpace = _parent_scene.space; | 775 | m_targetSpace = _parent_scene.space; |
774 | } | 776 | } |
775 | 777 | ||
778 | _triMeshData = IntPtr.Zero; | ||
779 | |||
776 | m_taintserial = null; | 780 | m_taintserial = null; |
777 | m_primName = primName; | 781 | m_primName = primName; |
778 | m_taintadd = true; | 782 | m_taintadd = true; |
@@ -1762,7 +1766,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1762 | 1766 | ||
1763 | private static Dictionary<IMesh, IntPtr> m_MeshToTriMeshMap = new Dictionary<IMesh, IntPtr>(); | 1767 | private static Dictionary<IMesh, IntPtr> m_MeshToTriMeshMap = new Dictionary<IMesh, IntPtr>(); |
1764 | 1768 | ||
1765 | public void setMesh(OdeScene parent_scene, IMesh mesh) | 1769 | public bool setMesh(OdeScene parent_scene, IMesh mesh) |
1766 | { | 1770 | { |
1767 | // This sleeper is there to moderate how long it takes between | 1771 | // This sleeper is there to moderate how long it takes between |
1768 | // setting up the mesh and pre-processing it when we get rapid fire mesh requests on a single object | 1772 | // setting up the mesh and pre-processing it when we get rapid fire mesh requests on a single object |
@@ -1785,24 +1789,48 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1785 | disableBody(); | 1789 | disableBody(); |
1786 | } | 1790 | } |
1787 | } | 1791 | } |
1792 | |||
1793 | // do it on caller instead | ||
1794 | /* | ||
1795 | if (_triMeshData != IntPtr.Zero) | ||
1796 | { | ||
1797 | d.GeomTriMeshDataDestroy(_triMeshData); | ||
1798 | _triMeshData = IntPtr.Zero; | ||
1799 | } | ||
1800 | */ | ||
1788 | IntPtr vertices, indices; | 1801 | IntPtr vertices, indices; |
1789 | int vertexCount, indexCount; | 1802 | int vertexCount, indexCount; |
1790 | int vertexStride, triStride; | 1803 | int vertexStride, triStride; |
1791 | mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap | 1804 | mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap |
1792 | mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage | 1805 | mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage |
1793 | 1806 | ||
1807 | // warning this destroys the mesh for eventual future use. Only pinned float arrays stay valid | ||
1794 | mesh.releaseSourceMeshData(); // free up the original mesh data to save memory | 1808 | mesh.releaseSourceMeshData(); // free up the original mesh data to save memory |
1809 | |||
1810 | if (vertexCount == 0 || indexCount == 0) | ||
1811 | { | ||
1812 | m_log.WarnFormat("[PHYSICS]: Got invalid mesh on prim {0} at <{1},{2},{3}>. It can be a sculp with alpha channel in map. Replacing it by a small box.", Name, _position.X, _position.Y, _position.Z); | ||
1813 | _size.X = 0.05f; | ||
1814 | _size.Y = 0.05f; | ||
1815 | _size.Z = 0.05f; | ||
1816 | return false; | ||
1817 | } | ||
1818 | |||
1819 | /* | ||
1795 | if (m_MeshToTriMeshMap.ContainsKey(mesh)) | 1820 | if (m_MeshToTriMeshMap.ContainsKey(mesh)) |
1796 | { | 1821 | { |
1797 | _triMeshData = m_MeshToTriMeshMap[mesh]; | 1822 | _triMeshData = m_MeshToTriMeshMap[mesh]; |
1798 | } | 1823 | } |
1799 | else | 1824 | else |
1825 | */ | ||
1826 | |||
1827 | |||
1800 | { | 1828 | { |
1801 | _triMeshData = d.GeomTriMeshDataCreate(); | 1829 | _triMeshData = d.GeomTriMeshDataCreate(); |
1802 | 1830 | ||
1803 | d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride); | 1831 | d.GeomTriMeshDataBuildSimple(_triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride); |
1804 | d.GeomTriMeshDataPreprocess(_triMeshData); | 1832 | d.GeomTriMeshDataPreprocess(_triMeshData); |
1805 | m_MeshToTriMeshMap[mesh] = _triMeshData; | 1833 | // m_MeshToTriMeshMap[mesh] = _triMeshData; |
1806 | } | 1834 | } |
1807 | 1835 | ||
1808 | _parent_scene.waitForSpaceUnlock(m_targetSpace); | 1836 | _parent_scene.waitForSpaceUnlock(m_targetSpace); |
@@ -1810,13 +1838,23 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1810 | { | 1838 | { |
1811 | // if (prim_geom == IntPtr.Zero) // setGeom takes care of phys engine recreate and prim_geom pointer | 1839 | // if (prim_geom == IntPtr.Zero) // setGeom takes care of phys engine recreate and prim_geom pointer |
1812 | // { | 1840 | // { |
1813 | SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null)); | 1841 | // SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, parent_scene.triCallback, null, null)); |
1842 | SetGeom(d.CreateTriMesh(m_targetSpace, _triMeshData, null, null, null)); | ||
1814 | // } | 1843 | // } |
1815 | } | 1844 | } |
1816 | catch (AccessViolationException) | 1845 | catch (Exception e) |
1817 | { | 1846 | { |
1818 | m_log.Error("[PHYSICS]: MESH LOCKED"); | 1847 | m_log.ErrorFormat("[PHYSICS]: Create trimesh failed on prim {0} : {1}",Name,e.Message); |
1819 | return; | 1848 | |
1849 | if (_triMeshData != IntPtr.Zero) | ||
1850 | { | ||
1851 | d.GeomTriMeshDataDestroy(_triMeshData); | ||
1852 | _triMeshData = IntPtr.Zero; | ||
1853 | } | ||
1854 | _size.X = 0.05f; | ||
1855 | _size.Y = 0.05f; | ||
1856 | _size.Z = 0.05f; | ||
1857 | return false; | ||
1820 | } | 1858 | } |
1821 | 1859 | ||
1822 | 1860 | ||
@@ -1828,6 +1866,7 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1828 | 1866 | ||
1829 | // enableBody(); | 1867 | // enableBody(); |
1830 | // } | 1868 | // } |
1869 | return true; | ||
1831 | } | 1870 | } |
1832 | 1871 | ||
1833 | public void ProcessTaints(float timestep) //============================================================================= | 1872 | public void ProcessTaints(float timestep) //============================================================================= |
@@ -1837,6 +1876,9 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
1837 | changeadd(timestep); | 1876 | changeadd(timestep); |
1838 | } | 1877 | } |
1839 | 1878 | ||
1879 | if (m_taintremove) | ||
1880 | return; | ||
1881 | |||
1840 | if (prim_geom != IntPtr.Zero) | 1882 | if (prim_geom != IntPtr.Zero) |
1841 | { | 1883 | { |
1842 | if (!_position.ApproxEquals(m_taintposition, 0f)) | 1884 | if (!_position.ApproxEquals(m_taintposition, 0f)) |
@@ -2286,75 +2328,62 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
2286 | 2328 | ||
2287 | public void CreateGeom(IntPtr m_targetSpace, IMesh _mesh) | 2329 | public void CreateGeom(IntPtr m_targetSpace, IMesh _mesh) |
2288 | { | 2330 | { |
2331 | bool gottrimesh = false; | ||
2332 | |||
2333 | if (_triMeshData != IntPtr.Zero) | ||
2334 | { | ||
2335 | d.GeomTriMeshDataDestroy(_triMeshData); | ||
2336 | _triMeshData = IntPtr.Zero; | ||
2337 | } | ||
2338 | |||
2289 | if (_mesh != null) // Special - make mesh | 2339 | if (_mesh != null) // Special - make mesh |
2290 | { | 2340 | { |
2291 | setMesh(_parent_scene, _mesh); | 2341 | gottrimesh = setMesh(_parent_scene, _mesh); |
2292 | } | 2342 | } |
2293 | else // not a mesh | 2343 | |
2344 | if (!gottrimesh) // not a mesh | ||
2294 | { | 2345 | { |
2295 | if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) // special profile?? | 2346 | IntPtr geo = IntPtr.Zero; |
2347 | |||
2348 | if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1 | ||
2349 | && _size.X == _size.Y && _size.X == _size.Z) | ||
2296 | { | 2350 | { |
2297 | if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) // Equi-size | 2351 | // its a sphere |
2352 | _parent_scene.waitForSpaceUnlock(m_targetSpace); | ||
2353 | try | ||
2298 | { | 2354 | { |
2299 | if (((_size.X / 2f) > 0f)) // Has size | 2355 | geo = d.CreateSphere(m_targetSpace, _size.X * 0.5f); |
2300 | { | ||
2301 | _parent_scene.waitForSpaceUnlock(m_targetSpace); | ||
2302 | try | ||
2303 | { | ||
2304 | SetGeom(d.CreateSphere(m_targetSpace, _size.X / 2)); | ||
2305 | } | ||
2306 | catch (AccessViolationException) | ||
2307 | { | ||
2308 | m_log.Warn("[PHYSICS]: Unable to create physics proxy for object"); | ||
2309 | ode.dunlock(_parent_scene.world); | ||
2310 | return; | ||
2311 | } | ||
2312 | } | ||
2313 | else | ||
2314 | { | ||
2315 | _parent_scene.waitForSpaceUnlock(m_targetSpace); | ||
2316 | try | ||
2317 | { | ||
2318 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); | ||
2319 | } | ||
2320 | catch (AccessViolationException) | ||
2321 | { | ||
2322 | m_log.Warn("[PHYSICS]: Unable to create physics proxy for object"); | ||
2323 | ode.dunlock(_parent_scene.world); | ||
2324 | return; | ||
2325 | } | ||
2326 | } | ||
2327 | } | 2356 | } |
2328 | else // not equi-size | 2357 | catch (Exception e) |
2329 | { | 2358 | { |
2330 | _parent_scene.waitForSpaceUnlock(m_targetSpace); | 2359 | m_log.WarnFormat("[PHYSICS]: Unable to create basic sphere for object {0}", e.Message); |
2331 | try | 2360 | geo = IntPtr.Zero; |
2332 | { | 2361 | ode.dunlock(_parent_scene.world); |
2333 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); | ||
2334 | } | ||
2335 | catch (AccessViolationException) | ||
2336 | { | ||
2337 | m_log.Warn("[PHYSICS]: Unable to create physics proxy for object"); | ||
2338 | ode.dunlock(_parent_scene.world); | ||
2339 | return; | ||
2340 | } | ||
2341 | } | 2362 | } |
2342 | } | 2363 | } |
2343 | 2364 | else // make it a box | |
2344 | else // not special profile | ||
2345 | { | 2365 | { |
2346 | _parent_scene.waitForSpaceUnlock(m_targetSpace); | 2366 | _parent_scene.waitForSpaceUnlock(m_targetSpace); |
2347 | try | 2367 | try |
2348 | { | 2368 | { |
2349 | SetGeom(d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z)); | 2369 | geo = d.CreateBox(m_targetSpace, _size.X, _size.Y, _size.Z); |
2350 | } | 2370 | } |
2351 | catch (AccessViolationException) | 2371 | catch (Exception e) |
2352 | { | 2372 | { |
2353 | m_log.Warn("[PHYSICS]: Unable to create physics proxy for object"); | 2373 | m_log.WarnFormat("[PHYSICS]: Unable to create basic sphere for object {0}", e.Message); |
2374 | geo = IntPtr.Zero; | ||
2354 | ode.dunlock(_parent_scene.world); | 2375 | ode.dunlock(_parent_scene.world); |
2355 | return; | ||
2356 | } | 2376 | } |
2357 | } | 2377 | } |
2378 | |||
2379 | if (geo == IntPtr.Zero) | ||
2380 | { | ||
2381 | m_taintremove = true; | ||
2382 | _parent_scene.AddPhysicsActorTaint(this); | ||
2383 | return; | ||
2384 | } | ||
2385 | |||
2386 | SetGeom(geo); | ||
2358 | } | 2387 | } |
2359 | } | 2388 | } |
2360 | 2389 | ||
@@ -2372,18 +2401,17 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
2372 | { | 2401 | { |
2373 | if (_parent_scene.needsMeshing(_pbs)) | 2402 | if (_parent_scene.needsMeshing(_pbs)) |
2374 | { | 2403 | { |
2375 | // Don't need to re-enable body.. it's done in SetMesh | ||
2376 | try | 2404 | try |
2377 | { | 2405 | { |
2378 | _mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size, _parent_scene.meshSculptLOD, IsPhysical); | 2406 | _mesh = _parent_scene.mesher.CreateMesh(m_primName, _pbs, _size, (int)LevelOfDetail.High, true); |
2379 | } | 2407 | } |
2380 | catch | 2408 | catch |
2381 | { | 2409 | { |
2382 | //Don't continuously try to mesh prims when meshing has failed | 2410 | //Don't continuously try to mesh prims when meshing has failed |
2383 | m_meshfailed = true; | 2411 | m_meshfailed = true; |
2412 | _mesh = null; | ||
2413 | m_log.WarnFormat("[PHYSICS]: changeAdd CreateMesh fail on prim {0} at <{1},{2},{3}>", Name, _position.X, _position.Y, _position.Z); | ||
2384 | } | 2414 | } |
2385 | // createmesh returns null when it's a shape that isn't a cube. | ||
2386 | // m_log.Debug(m_localID); | ||
2387 | } | 2415 | } |
2388 | } | 2416 | } |
2389 | 2417 | ||
@@ -2630,17 +2658,17 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
2630 | try | 2658 | try |
2631 | { | 2659 | { |
2632 | if (_parent_scene.needsMeshing(_pbs)) | 2660 | if (_parent_scene.needsMeshing(_pbs)) |
2633 | mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); | 2661 | mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, (int)LevelOfDetail.High, true); |
2634 | } | 2662 | } |
2635 | catch | 2663 | catch |
2636 | { | 2664 | { |
2637 | m_meshfailed = true; | 2665 | m_meshfailed = true; |
2666 | mesh = null; | ||
2667 | m_log.WarnFormat("[PHYSICS]: changeSize CreateMesh fail on prim {0} at <{1},{2},{3}>", Name, _position.X, _position.Y, _position.Z); | ||
2638 | } | 2668 | } |
2639 | 2669 | ||
2640 | //IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); | 2670 | //IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); |
2641 | CreateGeom(m_targetSpace, mesh); | 2671 | CreateGeom(m_targetSpace, mesh); |
2642 | |||
2643 | |||
2644 | } | 2672 | } |
2645 | else | 2673 | else |
2646 | { | 2674 | { |
@@ -2732,18 +2760,23 @@ namespace OpenSim.Region.Physics.OdePlugin | |||
2732 | { | 2760 | { |
2733 | // Don't need to re-enable body.. it's done in SetMesh | 2761 | // Don't need to re-enable body.. it's done in SetMesh |
2734 | float meshlod = _parent_scene.meshSculptLOD; | 2762 | float meshlod = _parent_scene.meshSculptLOD; |
2763 | IMesh mesh; | ||
2735 | 2764 | ||
2736 | if (IsPhysical) | 2765 | if (IsPhysical) |
2737 | meshlod = _parent_scene.MeshSculptphysicalLOD; | 2766 | meshlod = _parent_scene.MeshSculptphysicalLOD; |
2738 | try | 2767 | try |
2739 | { | 2768 | { |
2740 | IMesh mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, meshlod, IsPhysical); | 2769 | mesh = _parent_scene.mesher.CreateMesh(oldname, _pbs, _size, (int)LevelOfDetail.High, true); |
2741 | CreateGeom(m_targetSpace, mesh); | ||
2742 | } | 2770 | } |
2743 | catch | 2771 | catch |
2744 | { | 2772 | { |
2773 | mesh = null; | ||
2745 | m_meshfailed = true; | 2774 | m_meshfailed = true; |
2775 | m_log.WarnFormat("[PHYSICS]: changeAdd CreateMesh fail on prim {0} at <{1},{2},{3}>", Name, _position.X, _position.Y, _position.Z); | ||
2746 | } | 2776 | } |
2777 | |||
2778 | CreateGeom(m_targetSpace, mesh); | ||
2779 | |||
2747 | // createmesh returns null when it doesn't mesh. | 2780 | // createmesh returns null when it doesn't mesh. |
2748 | } | 2781 | } |
2749 | else | 2782 | else |