OpenSim
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Events Macros
CollisionSounds.cs
Go to the documentation of this file.
1 /*
2  * Copyright (c) Contributors, http://opensimulator.org/
3  * See CONTRIBUTORS.TXT for a full list of copyright holders.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions are met:
7  * * Redistributions of source code must retain the above copyright
8  * notice, this list of conditions and the following disclaimer.
9  * * Redistributions in binary form must reproduce the above copyright
10  * notice, this list of conditions and the following disclaimer in the
11  * documentation and/or other materials provided with the distribution.
12  * * Neither the name of the OpenSimulator Project nor the
13  * names of its contributors may be used to endorse or promote products
14  * derived from this software without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19  * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26  */
27 // Ubit 2012
28 
29 using System;
30 using System.Reflection;
31 using System.Collections.Generic;
32 using OpenMetaverse;
33 using OpenSim.Framework;
34 using log4net;
35 
36 namespace OpenSim.Region.Framework.Scenes
37 {
38  public struct CollisionForSoundInfo
39  {
40  public uint colliderID;
41  public Vector3 position;
42  public float relativeVel;
43  }
44 
45  public static class CollisionSounds
46  {
47  private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
48 
49  private const int MaxMaterials = 7;
50  // part part
51 
52  private static UUID snd_StoneStone = new UUID("be7295c0-a158-11e1-b3dd-0800200c9a66");
53  private static UUID snd_StoneMetal = new UUID("be7295c0-a158-11e1-b3dd-0800201c9a66");
54  private static UUID snd_StoneGlass = new UUID("be7295c0-a158-11e1-b3dd-0800202c9a66");
55  private static UUID snd_StoneWood = new UUID("be7295c0-a158-11e1-b3dd-0800203c9a66");
56  private static UUID snd_StoneFlesh = new UUID("be7295c0-a158-11e1-b3dd-0800204c9a66");
57  private static UUID snd_StonePlastic = new UUID("be7295c0-a158-11e1-b3dd-0800205c9a66");
58  private static UUID snd_StoneRubber = new UUID("be7295c0-a158-11e1-b3dd-0800206c9a66");
59 
60  private static UUID snd_MetalMetal = new UUID("be7295c0-a158-11e1-b3dd-0801201c9a66");
61  private static UUID snd_MetalGlass = new UUID("be7295c0-a158-11e1-b3dd-0801202c9a66");
62  private static UUID snd_MetalWood = new UUID("be7295c0-a158-11e1-b3dd-0801203c9a66");
63  private static UUID snd_MetalFlesh = new UUID("be7295c0-a158-11e1-b3dd-0801204c9a66");
64  private static UUID snd_MetalPlastic = new UUID("be7295c0-a158-11e1-b3dd-0801205c9a66");
65  private static UUID snd_MetalRubber = new UUID("be7295c0-a158-11e1-b3dd-0801206c9a66");
66 
67  private static UUID snd_GlassGlass = new UUID("be7295c0-a158-11e1-b3dd-0802202c9a66");
68  private static UUID snd_GlassWood = new UUID("be7295c0-a158-11e1-b3dd-0802203c9a66");
69  private static UUID snd_GlassFlesh = new UUID("be7295c0-a158-11e1-b3dd-0802204c9a66");
70  private static UUID snd_GlassPlastic = new UUID("be7295c0-a158-11e1-b3dd-0802205c9a66");
71  private static UUID snd_GlassRubber = new UUID("be7295c0-a158-11e1-b3dd-0802206c9a66");
72 
73  private static UUID snd_WoodWood = new UUID("be7295c0-a158-11e1-b3dd-0803203c9a66");
74  private static UUID snd_WoodFlesh = new UUID("be7295c0-a158-11e1-b3dd-0803204c9a66");
75  private static UUID snd_WoodPlastic = new UUID("be7295c0-a158-11e1-b3dd-0803205c9a66");
76  private static UUID snd_WoodRubber = new UUID("be7295c0-a158-11e1-b3dd-0803206c9a66");
77 
78  private static UUID snd_FleshFlesh = new UUID("be7295c0-a158-11e1-b3dd-0804204c9a66");
79  private static UUID snd_FleshPlastic = new UUID("be7295c0-a158-11e1-b3dd-0804205c9a66");
80  private static UUID snd_FleshRubber = new UUID("be7295c0-a158-11e1-b3dd-0804206c9a66");
81 
82  private static UUID snd_PlasticPlastic = new UUID("be7295c0-a158-11e1-b3dd-0805205c9a66");
83  private static UUID snd_PlasticRubber = new UUID("be7295c0-a158-11e1-b3dd-0805206c9a66");
84 
85  private static UUID snd_RubberRubber = new UUID("be7295c0-a158-11e1-b3dd-0806206c9a66");
86 
87  // terrain part
88  private static UUID snd_TerrainStone = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
89  private static UUID snd_TerrainMetal = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
90  private static UUID snd_TerrainGlass = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
91  private static UUID snd_TerrainWood = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
92  private static UUID snd_TerrainFlesh = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
93  private static UUID snd_TerrainPlastic = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
94  private static UUID snd_TerrainRubber = new UUID("be7295c0-a158-11e1-b3dd-0807200c9a66");
95 
96  public static UUID[] m_TerrainPart = {
97  snd_TerrainStone,
98  snd_TerrainMetal,
99  snd_TerrainGlass,
100  snd_TerrainWood,
101  snd_TerrainFlesh,
102  snd_TerrainPlastic,
103  snd_TerrainRubber
104  };
105 
106  // simetric sounds
107  public static UUID[] m_PartPart = {
108  snd_StoneStone, snd_StoneMetal, snd_StoneGlass, snd_StoneWood, snd_StoneFlesh, snd_StonePlastic, snd_StoneRubber,
109  snd_StoneMetal, snd_MetalMetal, snd_MetalGlass, snd_MetalWood, snd_MetalFlesh, snd_MetalPlastic, snd_MetalRubber,
110  snd_StoneGlass, snd_MetalGlass, snd_GlassGlass, snd_GlassWood, snd_GlassFlesh, snd_GlassPlastic, snd_GlassRubber,
111  snd_StoneWood, snd_MetalWood, snd_GlassWood, snd_WoodWood, snd_WoodFlesh, snd_WoodPlastic, snd_WoodRubber,
112  snd_StoneFlesh, snd_MetalFlesh, snd_GlassFlesh, snd_WoodFlesh, snd_FleshFlesh, snd_FleshPlastic, snd_FleshRubber,
113  snd_StonePlastic, snd_MetalPlastic, snd_GlassPlastic, snd_WoodPlastic, snd_FleshPlastic, snd_PlasticPlastic, snd_PlasticRubber,
114  snd_StoneRubber, snd_MetalRubber, snd_GlassRubber, snd_WoodRubber, snd_FleshRubber, snd_PlasticRubber, snd_RubberRubber
115  };
116 
117  public static void PartCollisionSound(SceneObjectPart part, List<CollisionForSoundInfo> collidersinfolist)
118  {
119  if (collidersinfolist.Count == 0 || part == null)
120  return;
121 
122  if (part.VolumeDetectActive || (part.Flags & PrimFlags.Physics) == 0)
123  return;
124 
125  if (part.ParentGroup == null)
126  return;
127 
128  if (part.CollisionSoundType < 0)
129  return;
130 
131  float volume = 0.0f;
132  bool HaveSound = false;
133 
134  UUID soundID = part.CollisionSound;
135 
136  if (part.CollisionSoundType > 0)
137  {
138  // soundID = part.CollisionSound;
139  volume = part.CollisionSoundVolume;
140  if (volume == 0.0f)
141  return;
142  HaveSound = true;
143  }
144 
145  bool doneownsound = false;
146 
147  int thisMaterial = (int)part.Material;
148  if (thisMaterial >= MaxMaterials)
149  thisMaterial = 3;
150  int thisMatScaled = thisMaterial * MaxMaterials;
151 
152  CollisionForSoundInfo colInfo;
153  uint id;
154 
155  for(int i = 0; i< collidersinfolist.Count; i++)
156  {
157  colInfo = collidersinfolist[i];
158 
159  id = colInfo.colliderID;
160  if (id == 0) // terrain collision
161  {
162  if (!doneownsound)
163  {
164  if (!HaveSound)
165  {
166  volume = Math.Abs(colInfo.relativeVel);
167  if (volume < 0.2f)
168  continue;
169 
170  volume *= volume * .0625f; // 4m/s == full volume
171  if (volume > 1.0f)
172  volume = 1.0f;
173 
174  soundID = m_TerrainPart[thisMaterial];
175  }
176  part.SendCollisionSound(soundID, volume, colInfo.position);
177  doneownsound = true;
178  }
179  continue;
180  }
181 
182  SceneObjectPart otherPart = part.ParentGroup.Scene.GetSceneObjectPart(id);
183  if (otherPart != null)
184  {
185  if (otherPart.CollisionSoundType < 0 || otherPart.VolumeDetectActive)
186  continue;
187 
188  if (!HaveSound)
189  {
190  if (otherPart.CollisionSoundType > 0)
191  {
192  soundID = otherPart.CollisionSound;
193  volume = otherPart.CollisionSoundVolume;
194  if (volume == 0.0f)
195  continue;
196  }
197  else
198  {
199  volume = Math.Abs(colInfo.relativeVel);
200  if (volume < 0.2f)
201  continue;
202 
203  volume *= volume * .0625f; // 4m/s == full volume
204  if (volume > 1.0f)
205  volume = 1.0f;
206 
207  int otherMaterial = (int)otherPart.Material;
208  if (otherMaterial >= MaxMaterials)
209  otherMaterial = 3;
210 
211  soundID = m_PartPart[thisMatScaled + otherMaterial];
212  }
213  }
214 
215  if (doneownsound)
216  otherPart.SendCollisionSound(soundID, volume, colInfo.position);
217  else
218  {
219  part.SendCollisionSound(soundID, volume, colInfo.position);
220  doneownsound = true;
221  }
222  }
223  }
224  }
225 
226  public static void AvatarCollisionSound(ScenePresence av, List<CollisionForSoundInfo> collidersinfolist)
227  {
228  if (collidersinfolist.Count == 0 || av == null)
229  return;
230 
231  UUID soundID;
232  int otherMaterial;
233 
234  int thisMaterial = 4; // flesh
235 
236  int thisMatScaled = thisMaterial * MaxMaterials;
237 
238  // bool doneownsound = false;
239 
240  CollisionForSoundInfo colInfo;
241  uint id;
242  float volume;
243 
244  for(int i = 0; i< collidersinfolist.Count; i++)
245  {
246  colInfo = collidersinfolist[i];
247 
248  id = colInfo.colliderID;
249 
250  if (id == 0) // no terrain collision sounds for now
251  {
252  continue;
253 // volume = Math.Abs(colInfo.relativeVel);
254 // if (volume < 0.2f)
255 // continue;
256 
257  }
258 
259  SceneObjectPart otherPart = av.Scene.GetSceneObjectPart(id);
260  if (otherPart != null)
261  {
262  if (otherPart.CollisionSoundType < 0)
263  continue;
264  if (otherPart.CollisionSoundType > 0 && otherPart.CollisionSoundVolume > 0f)
265  otherPart.SendCollisionSound(otherPart.CollisionSound, otherPart.CollisionSoundVolume, colInfo.position);
266  else
267  {
268  volume = Math.Abs(colInfo.relativeVel);
269  // Most noral collisions (running into walls, stairs)
270  // should never be heard.
271  if (volume < 3.2f)
272  continue;
273 // m_log.DebugFormat("Collision speed was {0}", volume);
274 
275  // Cap to 0.2 times volume because climbing stairs should not be noisy
276  // Also changed scaling
277  volume *= volume * .0125f; // 4m/s == volume 0.2
278  if (volume > 0.2f)
279  volume = 0.2f;
280  otherMaterial = (int)otherPart.Material;
281  if (otherMaterial >= MaxMaterials)
282  otherMaterial = 3;
283 
284  soundID = m_PartPart[thisMatScaled + otherMaterial];
285  otherPart.SendCollisionSound(soundID, volume, colInfo.position);
286  }
287  continue;
288  }
289 /*
290  else if (!doneownsound)
291  {
292  ScenePresence otherav = av.Scene.GetScenePresence(Id);
293  if (otherav != null && (!otherav.IsChildAgent))
294  {
295  soundID = snd_FleshFlesh;
296  av.SendCollisionSound(soundID, 1.0);
297  doneownsound = true;
298  }
299  }
300  */
301  }
302  }
303  }
304 }