aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/UbitOdePlugin
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs753
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs9
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs196
3 files changed, 799 insertions, 159 deletions
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs
new file mode 100644
index 0000000..9bf3667
--- /dev/null
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs
@@ -0,0 +1,753 @@
1/*
2 * AJLDuarte 2012
3 */
4
5using System;
6using System.Threading;
7using System.Collections.Generic;
8using System.IO;
9using System.Reflection;
10using System.Runtime.InteropServices;
11using System.Text;
12using OpenSim.Framework;
13using OpenSim.Region.Physics.Manager;
14using OdeAPI;
15using log4net;
16using Nini.Config;
17using OpenMetaverse;
18
19namespace OpenSim.Region.Physics.OdePlugin
20{
21 public class ODEMeshWorker
22 {
23 private ILog m_log;
24 private OdeScene m_scene;
25 private IMesher m_mesher;
26
27
28 public bool meshSculptedPrim = true;
29 public bool forceSimplePrimMeshing = false;
30 public float meshSculptLOD = 32;
31 public float MeshSculptphysicalLOD = 32;
32
33 private IntPtr m_workODEspace = IntPtr.Zero;
34
35 public ODEMeshWorker(OdeScene pScene, ILog pLog, IMesher pMesher, IntPtr pWorkSpace, IConfig pConfig)
36 {
37 m_scene = pScene;
38 m_log = pLog;
39 m_mesher = pMesher;
40 m_workODEspace = pWorkSpace;
41
42 if (pConfig != null)
43 {
44 forceSimplePrimMeshing = pConfig.GetBoolean("force_simple_prim_meshing", forceSimplePrimMeshing);
45 meshSculptedPrim = pConfig.GetBoolean("mesh_sculpted_prim", meshSculptedPrim);
46 meshSculptLOD = pConfig.GetFloat("mesh_lod", meshSculptLOD);
47 MeshSculptphysicalLOD = pConfig.GetFloat("mesh_physical_lod", MeshSculptphysicalLOD);
48 }
49 }
50
51 /// <summary>
52 /// Routine to figure out if we need to mesh this prim with our mesher
53 /// </summary>
54 /// <param name="pbs"></param>
55 /// <returns></returns>
56 public bool needsMeshing(PrimitiveBaseShape pbs)
57 {
58 // check sculpts or meshs
59 if (pbs.SculptEntry)
60 {
61 if (meshSculptedPrim)
62 return true;
63
64 if (pbs.SculptType == (byte)SculptType.Mesh) // always do meshs
65 return true;
66
67 return false;
68 }
69
70 if (forceSimplePrimMeshing)
71 return true;
72
73 // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim
74
75 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
76 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
77 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
78 {
79
80 if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
81 && pbs.ProfileHollow == 0
82 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
83 && pbs.PathBegin == 0 && pbs.PathEnd == 0
84 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
85 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
86 && pbs.PathShearX == 0 && pbs.PathShearY == 0)
87 {
88 return false;
89 }
90 }
91
92 // following code doesn't give meshs to boxes and spheres ever
93 // and it's odd.. so for now just return true if asked to force meshs
94 // hopefully mesher will fail if doesn't suport so things still get basic boxes
95
96 int iPropertiesNotSupportedDefault = 0;
97
98 if (pbs.ProfileHollow != 0)
99 iPropertiesNotSupportedDefault++;
100
101 if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
102 iPropertiesNotSupportedDefault++;
103
104 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
105 iPropertiesNotSupportedDefault++;
106
107 if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
108 iPropertiesNotSupportedDefault++;
109
110 if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
111 iPropertiesNotSupportedDefault++;
112
113 if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
114 iPropertiesNotSupportedDefault++;
115
116 if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
117 iPropertiesNotSupportedDefault++;
118
119 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X))
120 iPropertiesNotSupportedDefault++;
121
122 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1)
123 iPropertiesNotSupportedDefault++;
124
125 // test for torus
126 if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
127 {
128 if (pbs.PathCurve == (byte)Extrusion.Curve1)
129 {
130 iPropertiesNotSupportedDefault++;
131 }
132 }
133 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
134 {
135 if (pbs.PathCurve == (byte)Extrusion.Straight)
136 {
137 iPropertiesNotSupportedDefault++;
138 }
139
140 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
141 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
142 {
143 iPropertiesNotSupportedDefault++;
144 }
145 }
146 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
147 {
148 if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
149 {
150 iPropertiesNotSupportedDefault++;
151 }
152 }
153 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
154 {
155 if (pbs.PathCurve == (byte)Extrusion.Straight)
156 {
157 iPropertiesNotSupportedDefault++;
158 }
159 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
160 {
161 iPropertiesNotSupportedDefault++;
162 }
163 }
164
165 if (iPropertiesNotSupportedDefault == 0)
166 {
167 return false;
168 }
169 return true;
170 }
171
172 public IMesh getMesh(PhysicsActor actor, PrimitiveBaseShape ppbs, Vector3 psize, byte pshapetype)
173 {
174 if (!(actor is OdePrim))
175 return null;
176
177 IMesh mesh = null;
178 PrimitiveBaseShape pbs = ppbs;
179 Vector3 size = psize;
180 byte shapetype = pshapetype;
181
182 if (needsMeshing(pbs))
183 {
184 bool convex;
185 int clod = (int)LevelOfDetail.High;
186 if (shapetype == 0)
187 convex = false;
188 else
189 {
190 convex = true;
191 if (pbs.SculptType != (byte)SculptType.Mesh)
192 clod = (int)LevelOfDetail.Low;
193 }
194 mesh = m_mesher.GetMesh(actor.Name, pbs, size, clod, true, convex);
195 if (mesh == null)
196 {
197 if (!pbs.SculptEntry)
198 return m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex);
199
200 if (pbs.SculptTexture == UUID.Zero)
201 return null;
202
203 if (pbs.SculptType != (byte)SculptType.Mesh)
204 { // check for sculpt decoded image on cache)
205 if (File.Exists(System.IO.Path.Combine("j2kDecodeCache", "smap_" + pbs.SculptTexture.ToString())))
206 return m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex);
207 }
208
209 if (pbs.SculptData != null && pbs.SculptData.Length > 0)
210 return m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex);
211
212 ODEAssetRequest asr;
213 RequestAssetDelegate assetProvider = m_scene.RequestAssetMethod;
214 if (assetProvider != null)
215 asr = new ODEAssetRequest(this, assetProvider, actor, pbs, m_log);
216
217 return null;
218 }
219 }
220 return mesh;
221 }
222
223 private bool GetTriMeshGeo(ODEPhysRepData repData)
224 {
225 IntPtr vertices, indices;
226 IntPtr triMeshData = IntPtr.Zero;
227 IntPtr geo = IntPtr.Zero;
228 int vertexCount, indexCount;
229 int vertexStride, triStride;
230
231 PhysicsActor actor = repData.actor;
232
233 IMesh mesh = repData.mesh;
234
235 if (mesh == null)
236 {
237 mesh = getMesh(repData.actor, repData.pbs, repData.size, repData.shapetype);
238 }
239
240 if (mesh == null)
241 return false;
242
243 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap
244 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage
245
246 if (vertexCount == 0 || indexCount == 0)
247 {
248 m_log.WarnFormat("[PHYSICS]: Invalid mesh data on prim {0} mesh UUID {1}",
249 actor.Name, repData.pbs.SculptTexture.ToString());
250 mesh.releaseSourceMeshData();
251 return false;
252 }
253
254 repData.OBBOffset = mesh.GetCentroid();
255 repData.OBB = mesh.GetOBB();
256 repData.hasOBB = true;
257 repData.physCost = 0.0013f * (float)indexCount;
258
259 mesh.releaseSourceMeshData();
260
261 try
262 {
263 triMeshData = d.GeomTriMeshDataCreate();
264
265 d.GeomTriMeshDataBuildSimple(triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride);
266 d.GeomTriMeshDataPreprocess(triMeshData);
267
268 m_scene.waitForSpaceUnlock(m_workODEspace);
269 geo = d.CreateTriMesh(m_workODEspace, triMeshData, null, null, null);
270 }
271
272 catch (Exception e)
273 {
274 m_log.ErrorFormat("[PHYSICS]: SetGeom Mesh failed for {0} exception: {1}", actor.Name, e);
275 if (triMeshData != IntPtr.Zero)
276 {
277 d.GeomTriMeshDataDestroy(triMeshData);
278 repData.triMeshData = IntPtr.Zero;
279 }
280 repData.geo = IntPtr.Zero;
281 return false;
282 }
283
284 repData.geo = geo;
285 repData.triMeshData = triMeshData;
286 repData.curSpace = m_workODEspace;
287 return true;
288 }
289
290 public ODEPhysRepData CreateActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs, IMesh pMesh, Vector3 size, byte shapetype)
291 {
292 ODEPhysRepData repData = new ODEPhysRepData();
293
294 repData.actor = actor;
295 repData.pbs = pbs;
296 repData.mesh = pMesh;
297 repData.size = size;
298 repData.shapetype = shapetype;
299
300 IntPtr geo = IntPtr.Zero;
301 bool hasMesh = false;
302 if (needsMeshing(pbs))
303 {
304 if (GetTriMeshGeo(repData))
305 hasMesh = true;
306 else
307 repData.canColide = false;
308 }
309
310 if (!hasMesh)
311 {
312 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
313 && size.X == size.Y && size.Y == size.Z)
314 { // it's a sphere
315 m_scene.waitForSpaceUnlock(m_workODEspace);
316 try
317 {
318 geo = d.CreateSphere(m_workODEspace, size.X * 0.5f);
319 }
320 catch (Exception e)
321 {
322 m_log.WarnFormat("[PHYSICS]: Create sphere failed: {0}", e);
323 return null;
324 }
325 }
326 else
327 {// do it as a box
328 m_scene.waitForSpaceUnlock(m_workODEspace);
329 try
330 {
331 //Console.WriteLine(" CreateGeom 4");
332 geo = d.CreateBox(m_workODEspace, size.X, size.Y, size.Z);
333 }
334 catch (Exception e)
335 {
336 m_log.Warn("[PHYSICS]: Create box failed: {0}", e);
337 return null;
338 }
339 }
340
341 repData.physCost = 0.1f;
342 repData.streamCost = 1.0f;
343 repData.geo = geo;
344 }
345
346 repData.curSpace = m_workODEspace;
347
348 CalcVolumeData(repData);
349
350 return repData;
351 }
352
353 private void CalculateBasicPrimVolume(ODEPhysRepData repData)
354 {
355 PrimitiveBaseShape _pbs = repData.pbs;
356 Vector3 _size = repData.size;
357
358 float volume = _size.X * _size.Y * _size.Z; // default
359 float tmp;
360
361 float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f;
362 float hollowVolume = hollowAmount * hollowAmount;
363
364 switch (_pbs.ProfileShape)
365 {
366 case ProfileShape.Square:
367 // default box
368
369 if (_pbs.PathCurve == (byte)Extrusion.Straight)
370 {
371 if (hollowAmount > 0.0)
372 {
373 switch (_pbs.HollowShape)
374 {
375 case HollowShape.Square:
376 case HollowShape.Same:
377 break;
378
379 case HollowShape.Circle:
380
381 hollowVolume *= 0.78539816339f;
382 break;
383
384 case HollowShape.Triangle:
385
386 hollowVolume *= (0.5f * .5f);
387 break;
388
389 default:
390 hollowVolume = 0;
391 break;
392 }
393 volume *= (1.0f - hollowVolume);
394 }
395 }
396
397 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
398 {
399 //a tube
400
401 volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX);
402 tmp = 1.0f - 2.0e-2f * (float)(200 - _pbs.PathScaleY);
403 volume -= volume * tmp * tmp;
404
405 if (hollowAmount > 0.0)
406 {
407 hollowVolume *= hollowAmount;
408
409 switch (_pbs.HollowShape)
410 {
411 case HollowShape.Square:
412 case HollowShape.Same:
413 break;
414
415 case HollowShape.Circle:
416 hollowVolume *= 0.78539816339f;
417 break;
418
419 case HollowShape.Triangle:
420 hollowVolume *= 0.5f * 0.5f;
421 break;
422 default:
423 hollowVolume = 0;
424 break;
425 }
426 volume *= (1.0f - hollowVolume);
427 }
428 }
429
430 break;
431
432 case ProfileShape.Circle:
433
434 if (_pbs.PathCurve == (byte)Extrusion.Straight)
435 {
436 volume *= 0.78539816339f; // elipse base
437
438 if (hollowAmount > 0.0)
439 {
440 switch (_pbs.HollowShape)
441 {
442 case HollowShape.Same:
443 case HollowShape.Circle:
444 break;
445
446 case HollowShape.Square:
447 hollowVolume *= 0.5f * 2.5984480504799f;
448 break;
449
450 case HollowShape.Triangle:
451 hollowVolume *= .5f * 1.27323954473516f;
452 break;
453
454 default:
455 hollowVolume = 0;
456 break;
457 }
458 volume *= (1.0f - hollowVolume);
459 }
460 }
461
462 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
463 {
464 volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX);
465 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
466 volume *= (1.0f - tmp * tmp);
467
468 if (hollowAmount > 0.0)
469 {
470
471 // calculate the hollow volume by it's shape compared to the prim shape
472 hollowVolume *= hollowAmount;
473
474 switch (_pbs.HollowShape)
475 {
476 case HollowShape.Same:
477 case HollowShape.Circle:
478 break;
479
480 case HollowShape.Square:
481 hollowVolume *= 0.5f * 2.5984480504799f;
482 break;
483
484 case HollowShape.Triangle:
485 hollowVolume *= .5f * 1.27323954473516f;
486 break;
487
488 default:
489 hollowVolume = 0;
490 break;
491 }
492 volume *= (1.0f - hollowVolume);
493 }
494 }
495 break;
496
497 case ProfileShape.HalfCircle:
498 if (_pbs.PathCurve == (byte)Extrusion.Curve1)
499 {
500 volume *= 0.5236f;
501
502 if (hollowAmount > 0.0)
503 {
504 hollowVolume *= hollowAmount;
505
506 switch (_pbs.HollowShape)
507 {
508 case HollowShape.Circle:
509 case HollowShape.Triangle: // diference in sl is minor and odd
510 case HollowShape.Same:
511 break;
512
513 case HollowShape.Square:
514 hollowVolume *= 0.909f;
515 break;
516
517 // case HollowShape.Triangle:
518 // hollowVolume *= .827f;
519 // break;
520 default:
521 hollowVolume = 0;
522 break;
523 }
524 volume *= (1.0f - hollowVolume);
525 }
526
527 }
528 break;
529
530 case ProfileShape.EquilateralTriangle:
531
532 if (_pbs.PathCurve == (byte)Extrusion.Straight)
533 {
534 volume *= 0.32475953f;
535
536 if (hollowAmount > 0.0)
537 {
538
539 // calculate the hollow volume by it's shape compared to the prim shape
540 switch (_pbs.HollowShape)
541 {
542 case HollowShape.Same:
543 case HollowShape.Triangle:
544 hollowVolume *= .25f;
545 break;
546
547 case HollowShape.Square:
548 hollowVolume *= 0.499849f * 3.07920140172638f;
549 break;
550
551 case HollowShape.Circle:
552 // Hollow shape is a perfect cyllinder in respect to the cube's scale
553 // Cyllinder hollow volume calculation
554
555 hollowVolume *= 0.1963495f * 3.07920140172638f;
556 break;
557
558 default:
559 hollowVolume = 0;
560 break;
561 }
562 volume *= (1.0f - hollowVolume);
563 }
564 }
565 else if (_pbs.PathCurve == (byte)Extrusion.Curve1)
566 {
567 volume *= 0.32475953f;
568 volume *= 0.01f * (float)(200 - _pbs.PathScaleX);
569 tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY);
570 volume *= (1.0f - tmp * tmp);
571
572 if (hollowAmount > 0.0)
573 {
574
575 hollowVolume *= hollowAmount;
576
577 switch (_pbs.HollowShape)
578 {
579 case HollowShape.Same:
580 case HollowShape.Triangle:
581 hollowVolume *= .25f;
582 break;
583
584 case HollowShape.Square:
585 hollowVolume *= 0.499849f * 3.07920140172638f;
586 break;
587
588 case HollowShape.Circle:
589
590 hollowVolume *= 0.1963495f * 3.07920140172638f;
591 break;
592
593 default:
594 hollowVolume = 0;
595 break;
596 }
597 volume *= (1.0f - hollowVolume);
598 }
599 }
600 break;
601
602 default:
603 break;
604 }
605
606 float taperX1;
607 float taperY1;
608 float taperX;
609 float taperY;
610 float pathBegin;
611 float pathEnd;
612 float profileBegin;
613 float profileEnd;
614
615 if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible)
616 {
617 taperX1 = _pbs.PathScaleX * 0.01f;
618 if (taperX1 > 1.0f)
619 taperX1 = 2.0f - taperX1;
620 taperX = 1.0f - taperX1;
621
622 taperY1 = _pbs.PathScaleY * 0.01f;
623 if (taperY1 > 1.0f)
624 taperY1 = 2.0f - taperY1;
625 taperY = 1.0f - taperY1;
626 }
627 else
628 {
629 taperX = _pbs.PathTaperX * 0.01f;
630 if (taperX < 0.0f)
631 taperX = -taperX;
632 taperX1 = 1.0f - taperX;
633
634 taperY = _pbs.PathTaperY * 0.01f;
635 if (taperY < 0.0f)
636 taperY = -taperY;
637 taperY1 = 1.0f - taperY;
638 }
639
640 volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY);
641
642 pathBegin = (float)_pbs.PathBegin * 2.0e-5f;
643 pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f;
644 volume *= (pathEnd - pathBegin);
645
646 // this is crude aproximation
647 profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f;
648 profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f;
649 volume *= (profileEnd - profileBegin);
650
651 repData.volume = volume;
652 }
653
654 private void CalcVolumeData(ODEPhysRepData repData)
655 {
656 float volume;
657 Vector3 OBB = repData.size;
658 Vector3 OBBoffset;
659 IntPtr geo = repData.geo;
660
661 if (geo == IntPtr.Zero || repData.triMeshData == IntPtr.Zero)
662 {
663 OBB.X *= 0.5f;
664 OBB.Y *= 0.5f;
665 OBB.Z *= 0.5f;
666
667 repData.OBB = OBB;
668 repData.OBBOffset = Vector3.Zero;
669 }
670 else if (!repData.hasOBB) // should this happen?
671 {
672 d.AABB AABB;
673 d.GeomGetAABB(geo, out AABB); // get the AABB from engine geom
674
675 OBB.X = (AABB.MaxX - AABB.MinX) * 0.5f;
676 OBB.Y = (AABB.MaxY - AABB.MinY) * 0.5f;
677 OBB.Z = (AABB.MaxZ - AABB.MinZ) * 0.5f;
678 repData.OBB = OBB;
679 OBBoffset.X = (AABB.MaxX + AABB.MinX) * 0.5f;
680 OBBoffset.Y = (AABB.MaxY + AABB.MinY) * 0.5f;
681 OBBoffset.Z = (AABB.MaxZ + AABB.MinZ) * 0.5f;
682 repData.OBBOffset = Vector3.Zero;
683 }
684
685 // also its own inertia and mass
686 // keep using basic shape mass for now
687 CalculateBasicPrimVolume(repData);
688
689 if (repData.hasOBB)
690 {
691 OBB = repData.OBB;
692 float pc = repData.physCost;
693 float psf = OBB.X * (OBB.Y + OBB.Z) + OBB.Y * OBB.Z;
694 psf *= 1.33f * .2f;
695
696 pc *= psf;
697 if (pc < 0.1f)
698 pc = 0.1f;
699
700 repData.physCost = pc;
701 }
702 else
703 repData.physCost = 0.1f;
704 }
705 }
706
707 public class ODEAssetRequest
708 {
709 PhysicsActor m_actor;
710 ODEMeshWorker m_worker;
711 PrimitiveBaseShape m_pbs;
712 private ILog m_log;
713
714 public ODEAssetRequest(ODEMeshWorker pWorker, RequestAssetDelegate provider,
715 PhysicsActor pActor, PrimitiveBaseShape ppbs, ILog plog)
716 {
717 m_actor = pActor;
718 m_worker = pWorker;
719 m_pbs = ppbs;
720 m_log = plog;
721
722 if (provider == null)
723 return;
724
725 UUID assetID = m_pbs.SculptTexture;
726 if (assetID == UUID.Zero)
727 return;
728
729 provider(assetID, ODEassetReceived);
730 }
731
732 void ODEassetReceived(AssetBase asset)
733 {
734 if (m_actor != null && m_pbs != null)
735 {
736 if (asset != null)
737 {
738 if (asset.Data != null && asset.Data.Length > 0)
739 {
740 m_pbs.SculptData = asset.Data;
741 m_actor.Shape = m_pbs;
742 }
743 else
744 m_log.WarnFormat("[PHYSICS]: asset provider returned invalid mesh data for prim {0} asset UUID {1}.",
745 m_actor.Name, asset.ID.ToString());
746 }
747 else
748 m_log.WarnFormat("[PHYSICS]: asset provider returned null asset fo mesh of prim {0}.",
749 m_actor.Name);
750 }
751 }
752 }
753} \ No newline at end of file
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
index f2f4725..f328066 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEPrim.cs
@@ -1080,7 +1080,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1080 bounce = parent_scene.m_materialContactsData[(int)Material.Wood].bounce; 1080 bounce = parent_scene.m_materialContactsData[(int)Material.Wood].bounce;
1081 1081
1082 CalcPrimBodyData(); 1082 CalcPrimBodyData();
1083 1083/*
1084 m_mesh = null; 1084 m_mesh = null;
1085 if (_parent_scene.needsMeshing(pbs) && (pbs.SculptData.Length > 0)) 1085 if (_parent_scene.needsMeshing(pbs) && (pbs.SculptData.Length > 0))
1086 { 1086 {
@@ -1096,6 +1096,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1096 } 1096 }
1097 m_mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, clod, true, convex); 1097 m_mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, clod, true, convex);
1098 } 1098 }
1099*/
1100 m_mesh = _parent_scene.m_meshWorker.getMesh(this, pbs, _size, m_shapetype);
1099 1101
1100 m_building = true; // control must set this to false when done 1102 m_building = true; // control must set this to false when done
1101 1103
@@ -1351,6 +1353,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1351 { 1353 {
1352 if (m_mesh == null) 1354 if (m_mesh == null)
1353 { 1355 {
1356/*
1354 bool convex; 1357 bool convex;
1355 int clod = (int)LevelOfDetail.High; 1358 int clod = (int)LevelOfDetail.High;
1356 1359
@@ -1364,6 +1367,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1364 } 1367 }
1365 1368
1366 mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, clod, true, convex); 1369 mesh = _parent_scene.mesher.CreateMesh(Name, _pbs, _size, clod, true, convex);
1370*/
1371 mesh = _parent_scene.m_meshWorker.getMesh(this, _pbs, _size, m_shapetype);
1367 } 1372 }
1368 else 1373 else
1369 { 1374 {
@@ -1476,7 +1481,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1476 hasOOBoffsetFromMesh = false; 1481 hasOOBoffsetFromMesh = false;
1477 m_NoColide = false; 1482 m_NoColide = false;
1478 1483
1479 if (_parent_scene.needsMeshing(_pbs)) 1484 if (_parent_scene.m_meshWorker.needsMeshing(_pbs))
1480 { 1485 {
1481 haveMesh = setMesh(_parent_scene); // this will give a mesh to non trivial known prims 1486 haveMesh = setMesh(_parent_scene); // this will give a mesh to non trivial known prims
1482 if (!haveMesh) 1487 if (!haveMesh)
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
index f126644..d426112 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/OdeScene.cs
@@ -60,6 +60,29 @@ namespace OpenSim.Region.Physics.OdePlugin
60 public int lastframe; 60 public int lastframe;
61 } 61 }
62 62
63 public class ODEPhysRepData
64 {
65 public PhysicsActor actor;
66 public IntPtr geo = IntPtr.Zero;
67 public IntPtr triMeshData = IntPtr.Zero;
68 public IMesh mesh;
69 public IntPtr curSpace = IntPtr.Zero;
70 public PrimitiveBaseShape pbs;
71
72 public Vector3 size = Vector3.Zero;
73 public Vector3 OBB = Vector3.Zero;
74 public Vector3 OBBOffset = Vector3.Zero;
75
76 public float volume;
77
78 public float physCost = 0.0f;
79 public float streamCost = 0;
80 public byte shapetype = 0;
81 public bool canColide = true;
82 public bool hasOBB = false;
83 public bool hasMeshVolume = false;
84 }
85
63 // colision flags of things others can colide with 86 // colision flags of things others can colide with
64 // rays, sensors, probes removed since can't be colided with 87 // rays, sensors, probes removed since can't be colided with
65 // The top space where things are placed provided further selection 88 // The top space where things are placed provided further selection
@@ -230,11 +253,6 @@ namespace OpenSim.Region.Physics.OdePlugin
230 private float minimumGroundFlightOffset = 3f; 253 private float minimumGroundFlightOffset = 3f;
231 public float maximumMassObject = 10000.01f; 254 public float maximumMassObject = 10000.01f;
232 255
233 public bool meshSculptedPrim = true;
234 public bool forceSimplePrimMeshing = false;
235
236 public float meshSculptLOD = 32;
237 public float MeshSculptphysicalLOD = 32;
238 256
239 public float geomDefaultDensity = 10.000006836f; 257 public float geomDefaultDensity = 10.000006836f;
240 258
@@ -302,6 +320,7 @@ namespace OpenSim.Region.Physics.OdePlugin
302 public IntPtr TopSpace; // the global space 320 public IntPtr TopSpace; // the global space
303 public IntPtr ActiveSpace; // space for active prims 321 public IntPtr ActiveSpace; // space for active prims
304 public IntPtr StaticSpace; // space for the static things around 322 public IntPtr StaticSpace; // space for the static things around
323 public IntPtr WorkSpace; // no collisions work space
305 324
306 // some speedup variables 325 // some speedup variables
307 private int spaceGridMaxX; 326 private int spaceGridMaxX;
@@ -328,7 +347,7 @@ namespace OpenSim.Region.Physics.OdePlugin
328 private PhysicsScene m_parentScene = null; 347 private PhysicsScene m_parentScene = null;
329 348
330 private ODERayCastRequestManager m_rayCastManager; 349 private ODERayCastRequestManager m_rayCastManager;
331 350 public ODEMeshWorker m_meshWorker;
332 351
333/* maybe needed if ode uses tls 352/* maybe needed if ode uses tls
334 private void checkThread() 353 private void checkThread()
@@ -361,6 +380,8 @@ namespace OpenSim.Region.Physics.OdePlugin
361 nearCallback = near; 380 nearCallback = near;
362 381
363 m_rayCastManager = new ODERayCastRequestManager(this); 382 m_rayCastManager = new ODERayCastRequestManager(this);
383
384
364 lock (OdeLock) 385 lock (OdeLock)
365 { 386 {
366 // Create the world and the first space 387 // Create the world and the first space
@@ -372,6 +393,7 @@ namespace OpenSim.Region.Physics.OdePlugin
372 // now the major subspaces 393 // now the major subspaces
373 ActiveSpace = d.HashSpaceCreate(TopSpace); 394 ActiveSpace = d.HashSpaceCreate(TopSpace);
374 StaticSpace = d.HashSpaceCreate(TopSpace); 395 StaticSpace = d.HashSpaceCreate(TopSpace);
396 WorkSpace = d.HashSpaceCreate(TopSpace);
375 } 397 }
376 catch 398 catch
377 { 399 {
@@ -381,10 +403,12 @@ namespace OpenSim.Region.Physics.OdePlugin
381 d.HashSpaceSetLevels(TopSpace, -2, 8); 403 d.HashSpaceSetLevels(TopSpace, -2, 8);
382 d.HashSpaceSetLevels(ActiveSpace, -2, 8); 404 d.HashSpaceSetLevels(ActiveSpace, -2, 8);
383 d.HashSpaceSetLevels(StaticSpace, -2, 8); 405 d.HashSpaceSetLevels(StaticSpace, -2, 8);
406 d.HashSpaceSetLevels(WorkSpace, -2, 8);
384 407
385 // demote to second level 408 // demote to second level
386 d.SpaceSetSublevel(ActiveSpace, 1); 409 d.SpaceSetSublevel(ActiveSpace, 1);
387 d.SpaceSetSublevel(StaticSpace, 1); 410 d.SpaceSetSublevel(StaticSpace, 1);
411 d.SpaceSetSublevel(WorkSpace, 1);
388 412
389 d.GeomSetCategoryBits(ActiveSpace, (uint)(CollisionCategories.Space | 413 d.GeomSetCategoryBits(ActiveSpace, (uint)(CollisionCategories.Space |
390 CollisionCategories.Geom | 414 CollisionCategories.Geom |
@@ -402,6 +426,9 @@ namespace OpenSim.Region.Physics.OdePlugin
402 )); 426 ));
403 d.GeomSetCollideBits(StaticSpace, 0); 427 d.GeomSetCollideBits(StaticSpace, 0);
404 428
429 d.GeomSetCategoryBits(WorkSpace, 0);
430 d.GeomSetCollideBits(WorkSpace, 0);
431
405 contactgroup = d.JointGroupCreate(0); 432 contactgroup = d.JointGroupCreate(0);
406 //contactgroup 433 //contactgroup
407 434
@@ -440,9 +467,11 @@ namespace OpenSim.Region.Physics.OdePlugin
440 467
441 int contactsPerCollision = 80; 468 int contactsPerCollision = 80;
442 469
470 IConfig physicsconfig = null;
471
443 if (m_config != null) 472 if (m_config != null)
444 { 473 {
445 IConfig physicsconfig = m_config.Configs["ODEPhysicsSettings"]; 474 physicsconfig = m_config.Configs["ODEPhysicsSettings"];
446 if (physicsconfig != null) 475 if (physicsconfig != null)
447 { 476 {
448 gravityx = physicsconfig.GetFloat("world_gravityx", gravityx); 477 gravityx = physicsconfig.GetFloat("world_gravityx", gravityx);
@@ -469,27 +498,7 @@ namespace OpenSim.Region.Physics.OdePlugin
469 498
470 geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", geomDefaultDensity); 499 geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", geomDefaultDensity);
471 bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", bodyFramesAutoDisable); 500 bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", bodyFramesAutoDisable);
472/* 501
473 bodyPIDD = physicsconfig.GetFloat("body_pid_derivative", bodyPIDD);
474 bodyPIDG = physicsconfig.GetFloat("body_pid_gain", bodyPIDG);
475*/
476 forceSimplePrimMeshing = physicsconfig.GetBoolean("force_simple_prim_meshing", forceSimplePrimMeshing);
477 meshSculptedPrim = physicsconfig.GetBoolean("mesh_sculpted_prim", meshSculptedPrim);
478 meshSculptLOD = physicsconfig.GetFloat("mesh_lod", meshSculptLOD);
479 MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", MeshSculptphysicalLOD);
480/*
481 if (Environment.OSVersion.Platform == PlatformID.Unix)
482 {
483 avPIDD = physicsconfig.GetFloat("av_pid_derivative_linux", avPIDD);
484 avPIDP = physicsconfig.GetFloat("av_pid_proportional_linux", avPIDP);
485 }
486 else
487 {
488
489 avPIDD = physicsconfig.GetFloat("av_pid_derivative_win", avPIDD);
490 avPIDP = physicsconfig.GetFloat("av_pid_proportional_win", avPIDP);
491 }
492*/
493 physics_logging = physicsconfig.GetBoolean("physics_logging", false); 502 physics_logging = physicsconfig.GetBoolean("physics_logging", false);
494 physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0); 503 physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0);
495 physics_logging_append_existing_logfile = physicsconfig.GetBoolean("physics_logging_append_existing_logfile", false); 504 physics_logging_append_existing_logfile = physicsconfig.GetBoolean("physics_logging_append_existing_logfile", false);
@@ -499,6 +508,8 @@ namespace OpenSim.Region.Physics.OdePlugin
499 } 508 }
500 } 509 }
501 510
511 m_meshWorker = new ODEMeshWorker(this, m_log, meshmerizer, WorkSpace, physicsconfig);
512
502 HalfOdeStep = ODE_STEPSIZE * 0.5f; 513 HalfOdeStep = ODE_STEPSIZE * 0.5f;
503 odetimestepMS = (int)(1000.0f * ODE_STEPSIZE +0.5f); 514 odetimestepMS = (int)(1000.0f * ODE_STEPSIZE +0.5f);
504 515
@@ -1615,135 +1626,6 @@ namespace OpenSim.Region.Physics.OdePlugin
1615 1626
1616 #endregion 1627 #endregion
1617 1628
1618 /// <summary>
1619 /// Routine to figure out if we need to mesh this prim with our mesher
1620 /// </summary>
1621 /// <param name="pbs"></param>
1622 /// <returns></returns>
1623 public bool needsMeshing(PrimitiveBaseShape pbs)
1624 {
1625 // check sculpts or meshs
1626 if (pbs.SculptEntry)
1627 {
1628 if (meshSculptedPrim)
1629 return true;
1630
1631 if (pbs.SculptType == (byte)SculptType.Mesh) // always do meshs
1632 return true;
1633
1634 return false;
1635 }
1636
1637 if (forceSimplePrimMeshing)
1638 return true;
1639
1640 // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since ODE can use an internal representation for the prim
1641
1642 if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight)
1643 || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1
1644 && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z))
1645 {
1646
1647 if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0
1648 && pbs.ProfileHollow == 0
1649 && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0
1650 && pbs.PathBegin == 0 && pbs.PathEnd == 0
1651 && pbs.PathTaperX == 0 && pbs.PathTaperY == 0
1652 && pbs.PathScaleX == 100 && pbs.PathScaleY == 100
1653 && pbs.PathShearX == 0 && pbs.PathShearY == 0)
1654 {
1655#if SPAM
1656 m_log.Warn("NonMesh");
1657#endif
1658 return false;
1659 }
1660 }
1661
1662 // following code doesn't give meshs to boxes and spheres ever
1663 // and it's odd.. so for now just return true if asked to force meshs
1664 // hopefully mesher will fail if doesn't suport so things still get basic boxes
1665
1666 int iPropertiesNotSupportedDefault = 0;
1667
1668 if (pbs.ProfileHollow != 0)
1669 iPropertiesNotSupportedDefault++;
1670
1671 if ((pbs.PathBegin != 0) || pbs.PathEnd != 0)
1672 iPropertiesNotSupportedDefault++;
1673
1674 if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0))
1675 iPropertiesNotSupportedDefault++;
1676
1677 if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0)
1678 iPropertiesNotSupportedDefault++;
1679
1680 if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100))
1681 iPropertiesNotSupportedDefault++;
1682
1683 if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0))
1684 iPropertiesNotSupportedDefault++;
1685
1686 if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight)
1687 iPropertiesNotSupportedDefault++;
1688
1689 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X))
1690 iPropertiesNotSupportedDefault++;
1691
1692 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte) Extrusion.Curve1)
1693 iPropertiesNotSupportedDefault++;
1694
1695 // test for torus
1696 if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square)
1697 {
1698 if (pbs.PathCurve == (byte)Extrusion.Curve1)
1699 {
1700 iPropertiesNotSupportedDefault++;
1701 }
1702 }
1703 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle)
1704 {
1705 if (pbs.PathCurve == (byte)Extrusion.Straight)
1706 {
1707 iPropertiesNotSupportedDefault++;
1708 }
1709
1710 // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits
1711 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
1712 {
1713 iPropertiesNotSupportedDefault++;
1714 }
1715 }
1716 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle)
1717 {
1718 if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2)
1719 {
1720 iPropertiesNotSupportedDefault++;
1721 }
1722 }
1723 else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle)
1724 {
1725 if (pbs.PathCurve == (byte)Extrusion.Straight)
1726 {
1727 iPropertiesNotSupportedDefault++;
1728 }
1729 else if (pbs.PathCurve == (byte)Extrusion.Curve1)
1730 {
1731 iPropertiesNotSupportedDefault++;
1732 }
1733 }
1734
1735 if (iPropertiesNotSupportedDefault == 0)
1736 {
1737#if SPAM
1738 m_log.Warn("NonMesh");
1739#endif
1740 return false;
1741 }
1742#if SPAM
1743 m_log.Debug("Mesh");
1744#endif
1745 return true;
1746 }
1747 1629
1748 /// <summary> 1630 /// <summary>
1749 /// Called to queue a change to a actor 1631 /// Called to queue a change to a actor