diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/Physics/UbitOdePlugin/ODEMeshWorker.cs | 560 |
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 | ||
19 | namespace OpenSim.Region.Physics.OdePlugin | 19 | namespace 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 |