aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs560
1 files changed, 357 insertions, 203 deletions
diff --git a/OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs b/OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs
index 702c336..3fcbb1b 100644
--- a/OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs
+++ b/OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs
@@ -18,26 +18,63 @@ using OpenMetaverse;
18 18
19namespace OpenSim.Region.Physics.OdePlugin 19namespace OpenSim.Region.Physics.OdePlugin
20{ 20{
21 public enum meshWorkerCmnds : byte
22 {
23 nop = 0,
24 addnew,
25 changefull,
26 changesize,
27 changeshapetype,
28 getmesh,
29 }
30
31 public class ODEPhysRepData
32 {
33 public PhysicsActor actor;
34 public PrimitiveBaseShape pbs;
35 public IMesh mesh;
36
37 public Vector3 size;
38 public Vector3 OBB;
39 public Vector3 OBBOffset;
40
41 public float volume;
42
43 public float physCost;
44 public float streamCost;
45 public byte shapetype;
46 public bool hasOBB;
47 public bool hasMeshVolume;
48 public AssetState assetState;
49 public UUID? assetID;
50 public meshWorkerCmnds comand;
51 }
52
53
54
21 public class ODEMeshWorker 55 public class ODEMeshWorker
22 { 56 {
57
23 private ILog m_log; 58 private ILog m_log;
24 private OdeScene m_scene; 59 private OdeScene m_scene;
25 private IMesher m_mesher; 60 private IMesher m_mesher;
26 61
27
28 public bool meshSculptedPrim = true; 62 public bool meshSculptedPrim = true;
29 public bool forceSimplePrimMeshing = false; 63 public bool forceSimplePrimMeshing = false;
30 public float meshSculptLOD = 32; 64 public float meshSculptLOD = 32;
31 public float MeshSculptphysicalLOD = 32; 65 public float MeshSculptphysicalLOD = 32;
32 66
33 private IntPtr m_workODEspace = IntPtr.Zero;
34 67
35 public ODEMeshWorker(OdeScene pScene, ILog pLog, IMesher pMesher, IntPtr pWorkSpace, IConfig pConfig) 68 private OpenSim.Framework.BlockingQueue<ODEPhysRepData> createqueue = new OpenSim.Framework.BlockingQueue<ODEPhysRepData>();
69 private bool m_running;
70
71 private Thread m_thread;
72
73 public ODEMeshWorker(OdeScene pScene, ILog pLog, IMesher pMesher, IConfig pConfig)
36 { 74 {
37 m_scene = pScene; 75 m_scene = pScene;
38 m_log = pLog; 76 m_log = pLog;
39 m_mesher = pMesher; 77 m_mesher = pMesher;
40 m_workODEspace = pWorkSpace;
41 78
42 if (pConfig != null) 79 if (pConfig != null)
43 { 80 {
@@ -46,8 +83,177 @@ namespace OpenSim.Region.Physics.OdePlugin
46 meshSculptLOD = pConfig.GetFloat("mesh_lod", meshSculptLOD); 83 meshSculptLOD = pConfig.GetFloat("mesh_lod", meshSculptLOD);
47 MeshSculptphysicalLOD = pConfig.GetFloat("mesh_physical_lod", MeshSculptphysicalLOD); 84 MeshSculptphysicalLOD = pConfig.GetFloat("mesh_physical_lod", MeshSculptphysicalLOD);
48 } 85 }
86 m_running = true;
87 m_thread = new Thread(DoWork);
88 m_thread.Start();
89 }
90
91 private void DoWork()
92 {
93 while(m_running)
94 {
95 ODEPhysRepData nextRep = createqueue.Dequeue();
96 if(!m_running)
97 return;
98 if (nextRep == null)
99 continue;
100 if (m_scene.haveActor(nextRep.actor))
101 {
102 switch (nextRep.comand)
103 {
104 case meshWorkerCmnds.changefull:
105 case meshWorkerCmnds.changeshapetype:
106 case meshWorkerCmnds.changesize:
107 if (CreateActorPhysRep(nextRep) && m_scene.haveActor(nextRep.actor))
108 m_scene.AddChange(nextRep.actor, changes.PhysRepData, nextRep);
109 break;
110 case meshWorkerCmnds.addnew:
111 if (CreateActorPhysRep(nextRep))
112 m_scene.AddChange(nextRep.actor, changes.AddPhysRep, nextRep);
113 break;
114 case meshWorkerCmnds.getmesh:
115 DoRepDataGetMesh(nextRep);
116 break;
117 }
118 }
119 }
120 }
121
122 public void Stop()
123 {
124 m_running = false;
125 m_thread.Abort();
126 }
127
128 public void ChangeActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs,
129 Vector3 size, byte shapetype)
130 {
131 ODEPhysRepData repData = new ODEPhysRepData();
132 repData.actor = actor;
133 repData.pbs = pbs;
134 repData.size = size;
135 repData.shapetype = shapetype;
136
137 // if (CheckMeshDone(repData))
138 {
139 CheckMeshDone(repData);
140 CalcVolumeData(repData);
141 m_scene.AddChange(actor, changes.PhysRepData, repData);
142 return;
143 }
144
145// repData.comand = meshWorkerCmnds.changefull;
146// createqueue.Enqueue(repData);
147 }
148
149 public void NewActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs,
150 Vector3 size, byte shapetype)
151 {
152 ODEPhysRepData repData = new ODEPhysRepData();
153 repData.actor = actor;
154 repData.pbs = pbs;
155 repData.size = size;
156 repData.shapetype = shapetype;
157
158 // bool done = CheckMeshDone(repData);
159
160 CheckMeshDone(repData);
161 CalcVolumeData(repData);
162 m_scene.AddChange(actor, changes.AddPhysRep, repData);
163// if (done)
164 return;
165
166// repData.comand = meshWorkerCmnds.addnew;
167// createqueue.Enqueue(repData);
168 }
169
170 public void RequestMeshAsset(ODEPhysRepData repData)
171 {
172 if (repData.assetState != AssetState.needAsset)
173 return;
174
175 if (repData.assetID == null || repData.assetID == UUID.Zero)
176 return;
177
178 repData.mesh = null;
179
180 repData.assetState = AssetState.loadingAsset;
181
182 repData.comand = meshWorkerCmnds.getmesh;
183 createqueue.Enqueue(repData);
184 }
185
186 public bool CreateActorPhysRep(ODEPhysRepData repData)
187 {
188 getMesh(repData);
189 IMesh mesh = repData.mesh;
190
191 if (mesh != null)
192 {
193 IntPtr vertices, indices;
194 int vertexCount, indexCount;
195 int vertexStride, triStride;
196
197 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount);
198 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount);
199
200 if (vertexCount == 0 || indexCount == 0)
201 {
202 m_log.WarnFormat("[PHYSICS]: Invalid mesh data on prim {0} mesh UUID {1}",
203 repData.actor.Name, repData.pbs.SculptTexture.ToString());
204 repData.assetState = AssetState.AssetFailed;
205 repData.hasOBB = false;
206 repData.mesh = null;
207 m_scene.mesher.ReleaseMesh(mesh);
208 }
209 else
210 {
211 repData.OBBOffset = mesh.GetCentroid();
212 repData.OBB = mesh.GetOBB();
213 repData.hasOBB = true;
214 repData.physCost = 0.0013f * (float)indexCount;
215 // todo
216 repData.streamCost = 1.0f;
217 mesh.releaseSourceMeshData();
218 }
219 }
220 CalcVolumeData(repData);
221 return true;
222 }
223
224 public void AssetLoaded(ODEPhysRepData repData)
225 {
226 if (m_scene.haveActor(repData.actor))
227 {
228 if (needsMeshing(repData.pbs)) // no need for pbs now?
229 {
230 repData.comand = meshWorkerCmnds.changefull;
231 createqueue.Enqueue(repData);
232 }
233 }
49 } 234 }
50 235
236 public void DoRepDataGetMesh(ODEPhysRepData repData)
237 {
238 if (!repData.pbs.SculptEntry)
239 return;
240
241 if (repData.assetState != AssetState.loadingAsset)
242 return;
243
244 if (repData.assetID == null || repData.assetID == UUID.Zero)
245 return;
246
247 if (repData.assetID != repData.pbs.SculptTexture)
248 return;
249
250 RequestAssetDelegate assetProvider = m_scene.RequestAssetMethod;
251 if (assetProvider == null)
252 return;
253 ODEAssetRequest asr = new ODEAssetRequest(this, assetProvider, repData, m_log);
254 }
255
256
51 /// <summary> 257 /// <summary>
52 /// Routine to figure out if we need to mesh this prim with our mesher 258 /// Routine to figure out if we need to mesh this prim with our mesher
53 /// </summary> 259 /// </summary>
@@ -169,194 +375,151 @@ namespace OpenSim.Region.Physics.OdePlugin
169 return true; 375 return true;
170 } 376 }
171 377
172 public IMesh getMesh(PhysicsActor actor, PrimitiveBaseShape ppbs, Vector3 psize, byte pshapetype) 378 public bool CheckMeshDone(ODEPhysRepData repData)
173 { 379 {
174 if (!(actor is OdePrim)) 380 PhysicsActor actor = repData.actor;
175 return null; 381 PrimitiveBaseShape pbs = repData.pbs;
176 382
177 IMesh mesh = null; 383 repData.mesh = null;
178 PrimitiveBaseShape pbs = ppbs; 384 repData.hasOBB = false;
179 Vector3 size = psize;
180 byte shapetype = pshapetype;
181 385
182 if (needsMeshing(pbs)) 386 if (!needsMeshing(pbs))
183 { 387 {
184 bool convex; 388 repData.assetState = AssetState.noNeedAsset;
185 int clod = (int)LevelOfDetail.High; 389 return true;
186 if (shapetype == 0) 390 }
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 391
217 return null; 392 if (pbs.SculptEntry)
393 {
394 if (repData.assetState == AssetState.AssetFailed)
395 {
396 if (pbs.SculptTexture == repData.assetID)
397 return true;
218 } 398 }
219 } 399 }
220 return mesh; 400 else
221 } 401 {
402 repData.assetState = AssetState.noNeedAsset;
403 repData.assetID = null;
404 }
222 405
223 private bool GetTriMeshGeo(ODEPhysRepData repData) 406 IMesh mesh = null;
224 {
225 IntPtr vertices, indices;
226 IntPtr triMeshData = IntPtr.Zero;
227 IntPtr geo = IntPtr.Zero;
228 int vertexCount, indexCount;
229 int vertexStride, triStride;
230 407
231 PhysicsActor actor = repData.actor; 408 Vector3 size = repData.size;
409 byte shapetype = repData.shapetype;
232 410
233 IMesh mesh = repData.mesh; 411 bool convex;
234 412
235 if (mesh == null) 413 int clod = (int)LevelOfDetail.High;
414 if (shapetype == 0)
415 convex = false;
416 else
236 { 417 {
237 mesh = getMesh(repData.actor, repData.pbs, repData.size, repData.shapetype); 418 convex = true;
419 if (pbs.SculptType != (byte)SculptType.Mesh)
420 clod = (int)LevelOfDetail.Low;
238 } 421 }
239 422 mesh = m_mesher.GetMesh(actor.Name, pbs, size, clod, true, convex);
240 if (mesh == null) 423 if (mesh == null)
424 {
425 if (pbs.SculptEntry)
426 {
427 if (pbs.SculptTexture != null && pbs.SculptTexture != UUID.Zero)
428 {
429 repData.assetID = pbs.SculptTexture;
430 repData.assetState = AssetState.needAsset;
431 }
432 else
433 repData.assetState = AssetState.AssetFailed;
434 }
241 return false; 435 return false;
436 }
242 437
243 mesh.getVertexListAsPtrToFloatArray(out vertices, out vertexStride, out vertexCount); // Note, that vertices are fixed in unmanaged heap 438 repData.mesh = mesh;
244 mesh.getIndexListAsPtrToIntArray(out indices, out triStride, out indexCount); // Also fixed, needs release after usage 439 if (pbs.SculptEntry)
245
246 if (vertexCount == 0 || indexCount == 0)
247 { 440 {
248 m_log.WarnFormat("[PHYSICS]: Invalid mesh data on prim {0} mesh UUID {1}", 441 repData.assetState = AssetState.AssetOK;
249 actor.Name, repData.pbs.SculptTexture.ToString()); 442 repData.assetID = pbs.SculptTexture;
250 mesh.releaseSourceMeshData(); 443 pbs.SculptData = Utils.EmptyBytes;
251 return false;
252 } 444 }
445 return true;
446 }
253 447
254 repData.OBBOffset = mesh.GetCentroid();
255 repData.OBB = mesh.GetOBB();
256 repData.hasOBB = true;
257 repData.physCost = 0.0013f * (float)indexCount;
258 448
259 mesh.releaseSourceMeshData(); 449 public bool getMesh(ODEPhysRepData repData)
450 {
451 PhysicsActor actor = repData.actor;
260 452
261 try 453 PrimitiveBaseShape pbs = repData.pbs;
262 {
263 triMeshData = d.GeomTriMeshDataCreate();
264 454
265 d.GeomTriMeshDataBuildSimple(triMeshData, vertices, vertexStride, vertexCount, indices, indexCount, triStride); 455 repData.mesh = null;
266 d.GeomTriMeshDataPreprocess(triMeshData); 456 repData.hasOBB = false;
267 457
268 m_scene.waitForSpaceUnlock(m_workODEspace); 458 if (!needsMeshing(pbs))
269 geo = d.CreateTriMesh(m_workODEspace, triMeshData, null, null, null); 459 return false;
270 }
271 460
272 catch (Exception e) 461 if (pbs.SculptEntry)
273 { 462 {
274 m_log.ErrorFormat("[PHYSICS]: SetGeom Mesh failed for {0} exception: {1}", actor.Name, e); 463 if (repData.assetState == AssetState.AssetFailed)
275 if (triMeshData != IntPtr.Zero)
276 { 464 {
277 d.GeomTriMeshDataDestroy(triMeshData); 465 if (pbs.SculptTexture == repData.assetID)
278 repData.triMeshData = IntPtr.Zero; 466 return true;
279 } 467 }
280 repData.geo = IntPtr.Zero;
281 return false;
282 } 468 }
283 469
284 repData.geo = geo; 470 repData.assetState = AssetState.noNeedAsset;
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 471
294 repData.actor = actor; 472 IMesh mesh = null;
295 repData.pbs = pbs; 473 Vector3 size = repData.size;
296 repData.mesh = pMesh; 474 byte shapetype = repData.shapetype;
297 repData.size = size;
298 repData.shapetype = shapetype;
299 475
300 IntPtr geo = IntPtr.Zero; 476 bool convex;
301 bool hasMesh = false; 477 int clod = (int)LevelOfDetail.High;
302 if (needsMeshing(pbs)) 478 if (shapetype == 0)
479 convex = false;
480 else
303 { 481 {
304 if (GetTriMeshGeo(repData)) 482 convex = true;
305 hasMesh = true; 483 if (pbs.SculptType != (byte)SculptType.Mesh)
306 else 484 clod = (int)LevelOfDetail.Low;
307 repData.NoColide = true;
308 } 485 }
309 486 mesh = m_mesher.GetMesh(actor.Name, pbs, size, clod, true, convex);
310 if (!hasMesh) 487 if (mesh == null)
311 { 488 {
312 if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 489 if (pbs.SculptEntry)
313 && size.X == size.Y && size.Y == size.Z) 490 {
314 { // it's a sphere 491 if (pbs.SculptTexture == UUID.Zero)
315 m_scene.waitForSpaceUnlock(m_workODEspace); 492 return false;
316 try 493
317 { 494 repData.assetID = pbs.SculptTexture;
318 geo = d.CreateSphere(m_workODEspace, size.X * 0.5f); 495 repData.assetState = AssetState.AssetOK;
319 } 496
320 catch (Exception e) 497 if (pbs.SculptData == null || pbs.SculptData.Length == 0)
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 { 498 {
336 m_log.Warn("[PHYSICS]: Create box failed: {0}", e); 499 repData.assetState = AssetState.needAsset;
337 return null; 500 return false;
338 } 501 }
339 } 502 }
340 503
341 repData.physCost = 0.1f; 504 mesh = m_mesher.CreateMesh(actor.Name, pbs, size, clod, true, convex);
342 repData.streamCost = 1.0f; 505
343 repData.geo = geo;
344 } 506 }
345
346 repData.curSpace = m_workODEspace;
347 507
348 CalcVolumeData(repData); 508 repData.mesh = mesh;
509 repData.pbs.SculptData = Utils.EmptyBytes;
349 510
350 return repData; 511 if (mesh == null)
351 } 512 {
513 if (pbs.SculptEntry)
514 repData.assetState = AssetState.AssetFailed;
352 515
353 public void ChangeActorPhysRep(PhysicsActor actor, PrimitiveBaseShape pbs, 516 return false;
354 Vector3 size, byte shapetype, MeshWorkerChange what) 517 }
355 { 518
356 ODEPhysRepData repData = CreateActorPhysRep(actor, pbs, null, size, shapetype); 519 if (pbs.SculptEntry)
357 repData.changed |= what; 520 repData.assetState = AssetState.AssetOK;
358 if (repData != null && actor != null) 521
359 ((OdePrim)actor).AddChange(changes.PhysRepData, repData); 522 return true;
360 } 523 }
361 524
362 private void CalculateBasicPrimVolume(ODEPhysRepData repData) 525 private void CalculateBasicPrimVolume(ODEPhysRepData repData)
@@ -662,46 +825,12 @@ namespace OpenSim.Region.Physics.OdePlugin
662 825
663 private void CalcVolumeData(ODEPhysRepData repData) 826 private void CalcVolumeData(ODEPhysRepData repData)
664 { 827 {
665 float volume;
666 Vector3 OBB = repData.size;
667 Vector3 OBBoffset;
668 IntPtr geo = repData.geo;
669
670 if (geo == IntPtr.Zero || repData.triMeshData == IntPtr.Zero)
671 {
672 OBB.X *= 0.5f;
673 OBB.Y *= 0.5f;
674 OBB.Z *= 0.5f;
675
676 repData.OBB = OBB;
677 repData.OBBOffset = Vector3.Zero;
678 }
679 else if (!repData.hasOBB) // should this happen?
680 {
681 d.AABB AABB;
682 d.GeomGetAABB(geo, out AABB); // get the AABB from engine geom
683
684 OBB.X = (AABB.MaxX - AABB.MinX) * 0.5f;
685 OBB.Y = (AABB.MaxY - AABB.MinY) * 0.5f;
686 OBB.Z = (AABB.MaxZ - AABB.MinZ) * 0.5f;
687 repData.OBB = OBB;
688 OBBoffset.X = (AABB.MaxX + AABB.MinX) * 0.5f;
689 OBBoffset.Y = (AABB.MaxY + AABB.MinY) * 0.5f;
690 OBBoffset.Z = (AABB.MaxZ + AABB.MinZ) * 0.5f;
691 repData.OBBOffset = Vector3.Zero;
692 }
693
694 // also its own inertia and mass
695 // keep using basic shape mass for now
696 CalculateBasicPrimVolume(repData);
697
698 if (repData.hasOBB) 828 if (repData.hasOBB)
699 { 829 {
700 OBB = repData.OBB; 830 Vector3 OBB = repData.OBB;
701 float pc = repData.physCost; 831 float pc = repData.physCost;
702 float psf = OBB.X * (OBB.Y + OBB.Z) + OBB.Y * OBB.Z; 832 float psf = OBB.X * (OBB.Y + OBB.Z) + OBB.Y * OBB.Z;
703 psf *= 1.33f * .2f; 833 psf *= 1.33f * .2f;
704
705 pc *= psf; 834 pc *= psf;
706 if (pc < 0.1f) 835 if (pc < 0.1f)
707 pc = 0.1f; 836 pc = 0.1f;
@@ -709,54 +838,79 @@ namespace OpenSim.Region.Physics.OdePlugin
709 repData.physCost = pc; 838 repData.physCost = pc;
710 } 839 }
711 else 840 else
841 {
842 Vector3 OBB = repData.size;
843 OBB.X *= 0.5f;
844 OBB.Y *= 0.5f;
845 OBB.Z *= 0.5f;
846
847 repData.OBB = OBB;
848 repData.OBBOffset = Vector3.Zero;
849
712 repData.physCost = 0.1f; 850 repData.physCost = 0.1f;
851 repData.streamCost = 1.0f;
852 }
853
854 CalculateBasicPrimVolume(repData);
713 } 855 }
714 } 856 }
715 857
716 public class ODEAssetRequest 858 public class ODEAssetRequest
717 { 859 {
718 PhysicsActor m_actor;
719 ODEMeshWorker m_worker; 860 ODEMeshWorker m_worker;
720 PrimitiveBaseShape m_pbs;
721 private ILog m_log; 861 private ILog m_log;
862 ODEPhysRepData repData;
722 863
723 public ODEAssetRequest(ODEMeshWorker pWorker, RequestAssetDelegate provider, 864 public ODEAssetRequest(ODEMeshWorker pWorker, RequestAssetDelegate provider,
724 PhysicsActor pActor, PrimitiveBaseShape ppbs, ILog plog) 865 ODEPhysRepData pRepData, ILog plog)
725 { 866 {
726 m_actor = pActor;
727 m_worker = pWorker; 867 m_worker = pWorker;
728 m_pbs = ppbs;
729 m_log = plog; 868 m_log = plog;
869 repData = pRepData;
730 870
871 repData.assetState = AssetState.AssetFailed;
731 if (provider == null) 872 if (provider == null)
732 return; 873 return;
733 874
734 UUID assetID = m_pbs.SculptTexture; 875 if (repData.assetID == null)
876 return;
877
878 UUID assetID = (UUID) repData.assetID;
735 if (assetID == UUID.Zero) 879 if (assetID == UUID.Zero)
736 return; 880 return;
737 881
882 repData.assetState = AssetState.loadingAsset;
738 provider(assetID, ODEassetReceived); 883 provider(assetID, ODEassetReceived);
739 } 884 }
740 885
741 void ODEassetReceived(AssetBase asset) 886 void ODEassetReceived(AssetBase asset)
742 { 887 {
743 if (m_actor != null && m_pbs != null) 888 repData.assetState = AssetState.AssetFailed;
889 if (asset != null)
744 { 890 {
745 if (asset != null) 891 if (asset.Data != null && asset.Data.Length > 0)
746 { 892 {
747 if (asset.Data != null && asset.Data.Length > 0) 893 if (!repData.pbs.SculptEntry)
748 { 894 return;
749 m_pbs.SculptData = asset.Data; 895 if (repData.pbs.SculptTexture != repData.assetID)
750 m_actor.Shape = m_pbs; 896 return;
751 } 897
752 else 898 // asset get may return a pointer to the same asset data
753 m_log.WarnFormat("[PHYSICS]: asset provider returned invalid mesh data for prim {0} asset UUID {1}.", 899 // for similar prims and we destroy with it
754 m_actor.Name, asset.ID.ToString()); 900 // so waste a lot of time stressing gc and hoping it clears things
901 // TODO avoid this
902 repData.pbs.SculptData = new byte[asset.Data.Length];
903 asset.Data.CopyTo(repData.pbs.SculptData,0);
904 repData.assetState = AssetState.AssetOK;
905 m_worker.AssetLoaded(repData);
755 } 906 }
756 else 907 else
757 m_log.WarnFormat("[PHYSICS]: asset provider returned null asset fo mesh of prim {0}.", 908 m_log.WarnFormat("[PHYSICS]: asset provider returned invalid mesh data for prim {0} asset UUID {1}.",
758 m_actor.Name); 909 repData.actor.Name, asset.ID.ToString());
759 } 910 }
911 else
912 m_log.WarnFormat("[PHYSICS]: asset provider returned null asset fo mesh of prim {0}.",
913 repData.actor.Name);
760 } 914 }
761 } 915 }
762} \ No newline at end of file 916} \ No newline at end of file