IMHOTEP Framework
 All Classes Namespaces Functions Variables Enumerations Enumerator Properties Pages
SteamVR_RenderModel.cs
1 //======= Copyright (c) Valve Corporation, All rights reserved. ===============
2 //
3 // Purpose: Render model of associated tracked object
4 //
5 //=============================================================================
6 
7 using UnityEngine;
8 using System.Collections;
9 using System.Collections.Generic;
10 using System.Runtime.InteropServices;
11 using Valve.VR;
12 
13 [ExecuteInEditMode]
14 public class SteamVR_RenderModel : MonoBehaviour
15 {
16  public SteamVR_TrackedObject.EIndex index = SteamVR_TrackedObject.EIndex.None;
17 
18  public const string modelOverrideWarning = "Model override is really only meant to be used in " +
19  "the scene view for lining things up; using it at runtime is discouraged. Use tracked device " +
20  "index instead to ensure the correct model is displayed for all users.";
21 
22  [Tooltip(modelOverrideWarning)]
23  public string modelOverride;
24 
25  [Tooltip("Shader to apply to model.")]
26  public Shader shader;
27 
28  [Tooltip("Enable to print out when render models are loaded.")]
29  public bool verbose = false;
30 
31  [Tooltip("If available, break down into separate components instead of loading as a single mesh.")]
32  public bool createComponents = true;
33 
34  [Tooltip("Update transforms of components at runtime to reflect user action.")]
35  public bool updateDynamically = true;
36 
37  // Additional controller settings for showing scrollwheel, etc.
38  public RenderModel_ControllerMode_State_t controllerModeState;
39 
40  // Name of the sub-object which represents the "local" coordinate space for each component.
41  public const string k_localTransformName = "attach";
42 
43  // Cached name of this render model for updating component transforms at runtime.
44  public string renderModelName { get; private set; }
45 
46  // If someone knows how to keep these from getting cleaned up every time
47  // you exit play mode, let me know. I've tried marking the RenderModel
48  // class below as [System.Serializable] and switching to normal public
49  // variables for mesh and material to get them to serialize properly,
50  // as well as tried marking the mesh and material objects as
51  // DontUnloadUnusedAsset, but Unity was still unloading them.
52  // The hashtable is preserving its entries, but the mesh and material
53  // variables are going null.
54 
55  public class RenderModel
56  {
57  public RenderModel(Mesh mesh, Material material)
58  {
59  this.mesh = mesh;
60  this.material = material;
61  }
62  public Mesh mesh { get; private set; }
63  public Material material { get; private set; }
64  }
65 
66  public static Hashtable models = new Hashtable();
67  public static Hashtable materials = new Hashtable();
68 
69  // Helper class to load render models interface on demand and clean up when done.
70  public sealed class RenderModelInterfaceHolder : System.IDisposable
71  {
72  private bool needsShutdown, failedLoadInterface;
73  private CVRRenderModels _instance;
74  public CVRRenderModels instance
75  {
76  get
77  {
78  if (_instance == null && !failedLoadInterface)
79  {
80  if (!SteamVR.active && !SteamVR.usingNativeSupport)
81  {
82  var error = EVRInitError.None;
83  OpenVR.Init(ref error, EVRApplicationType.VRApplication_Utility);
84  needsShutdown = true;
85  }
86 
87  _instance = OpenVR.RenderModels;
88  if (_instance == null)
89  {
90  Debug.LogError("Failed to load IVRRenderModels interface version " + OpenVR.IVRRenderModels_Version);
91  failedLoadInterface = true;
92  }
93  }
94  return _instance;
95  }
96  }
97  public void Dispose()
98  {
99  if (needsShutdown)
100  OpenVR.Shutdown();
101  }
102  }
103 
104  private void OnModelSkinSettingsHaveChanged(VREvent_t vrEvent)
105  {
106  if (!string.IsNullOrEmpty(renderModelName))
107  {
108  renderModelName = "";
109  UpdateModel();
110  }
111  }
112 
113  private void OnHideRenderModels(bool hidden)
114  {
115  var meshRenderer = GetComponent<MeshRenderer>();
116  if (meshRenderer != null)
117  meshRenderer.enabled = !hidden;
118  foreach (var child in transform.GetComponentsInChildren<MeshRenderer>())
119  child.enabled = !hidden;
120  }
121 
122  private void OnDeviceConnected(int i, bool connected)
123  {
124  if (i != (int)index)
125  return;
126 
127  if (connected)
128  {
129  UpdateModel();
130  }
131  }
132 
133  public void UpdateModel()
134  {
135  var system = OpenVR.System;
136  if (system == null)
137  return;
138 
139  var error = ETrackedPropertyError.TrackedProp_Success;
140  var capacity = system.GetStringTrackedDeviceProperty((uint)index, ETrackedDeviceProperty.Prop_RenderModelName_String, null, 0, ref error);
141  if (capacity <= 1)
142  {
143  Debug.LogError("Failed to get render model name for tracked object " + index);
144  return;
145  }
146 
147  var buffer = new System.Text.StringBuilder((int)capacity);
148  system.GetStringTrackedDeviceProperty((uint)index, ETrackedDeviceProperty.Prop_RenderModelName_String, buffer, capacity, ref error);
149 
150  var s = buffer.ToString();
151  if (renderModelName != s)
152  {
153  renderModelName = s;
154  StartCoroutine(SetModelAsync(s));
155  }
156  }
157 
158  IEnumerator SetModelAsync(string renderModelName)
159  {
160  if (string.IsNullOrEmpty(renderModelName))
161  yield break;
162 
163  // Preload all render models before asking for the data to create meshes.
164  using (var holder = new RenderModelInterfaceHolder())
165  {
166  var renderModels = holder.instance;
167  if (renderModels == null)
168  yield break;
169 
170  // Gather names of render models to preload.
171  string[] renderModelNames;
172 
173  var count = renderModels.GetComponentCount(renderModelName);
174  if (count > 0)
175  {
176  renderModelNames = new string[count];
177 
178  for (int i = 0; i < count; i++)
179  {
180  var capacity = renderModels.GetComponentName(renderModelName, (uint)i, null, 0);
181  if (capacity == 0)
182  continue;
183 
184  var componentName = new System.Text.StringBuilder((int)capacity);
185  if (renderModels.GetComponentName(renderModelName, (uint)i, componentName, capacity) == 0)
186  continue;
187 
188  capacity = renderModels.GetComponentRenderModelName(renderModelName, componentName.ToString(), null, 0);
189  if (capacity == 0)
190  continue;
191 
192  var name = new System.Text.StringBuilder((int)capacity);
193  if (renderModels.GetComponentRenderModelName(renderModelName, componentName.ToString(), name, capacity) == 0)
194  continue;
195 
196  var s = name.ToString();
197 
198  // Only need to preload if not already cached.
199  var model = models[s] as RenderModel;
200  if (model == null || model.mesh == null)
201  {
202  renderModelNames[i] = s;
203  }
204  }
205  }
206  else
207  {
208  // Only need to preload if not already cached.
209  var model = models[renderModelName] as RenderModel;
210  if (model == null || model.mesh == null)
211  {
212  renderModelNames = new string[] { renderModelName };
213  }
214  else
215  {
216  renderModelNames = new string[0];
217  }
218  }
219 
220  // Keep trying every 100ms until all components finish loading.
221  while (true)
222  {
223  var loading = false;
224  foreach (var name in renderModelNames)
225  {
226  if (string.IsNullOrEmpty(name))
227  continue;
228 
229  var pRenderModel = System.IntPtr.Zero;
230 
231  var error = renderModels.LoadRenderModel_Async(name, ref pRenderModel);
232  if (error == EVRRenderModelError.Loading)
233  {
234  loading = true;
235  }
236  else if (error == EVRRenderModelError.None)
237  {
238  // Preload textures as well.
239  var renderModel = MarshalRenderModel(pRenderModel);
240 
241  // Check the cache first.
242  var material = materials[renderModel.diffuseTextureId] as Material;
243  if (material == null || material.mainTexture == null)
244  {
245  var pDiffuseTexture = System.IntPtr.Zero;
246 
247  error = renderModels.LoadTexture_Async(renderModel.diffuseTextureId, ref pDiffuseTexture);
248  if (error == EVRRenderModelError.Loading)
249  {
250  loading = true;
251  }
252  }
253  }
254  }
255 
256  if (loading)
257  {
258  yield return new WaitForSecondsRealtime(0.1f);
259  }
260  else
261  {
262  break;
263  }
264  }
265  }
266 
267  bool success = SetModel(renderModelName);
268  SteamVR_Events.RenderModelLoaded.Send(this, success);
269  }
270 
271  private bool SetModel(string renderModelName)
272  {
273  StripMesh(gameObject);
274 
275  using (var holder = new RenderModelInterfaceHolder())
276  {
277  if (createComponents)
278  {
279  if (LoadComponents(holder, renderModelName))
280  {
281  UpdateComponents(holder.instance);
282  return true;
283  }
284 
285  Debug.Log("[" + gameObject.name + "] Render model does not support components, falling back to single mesh.");
286  }
287 
288  if (!string.IsNullOrEmpty(renderModelName))
289  {
290  var model = models[renderModelName] as RenderModel;
291  if (model == null || model.mesh == null)
292  {
293  var renderModels = holder.instance;
294  if (renderModels == null)
295  return false;
296 
297  if (verbose)
298  Debug.Log("Loading render model " + renderModelName);
299 
300  model = LoadRenderModel(renderModels, renderModelName, renderModelName);
301  if (model == null)
302  return false;
303 
304  models[renderModelName] = model;
305  }
306 
307  gameObject.AddComponent<MeshFilter>().mesh = model.mesh;
308  gameObject.AddComponent<MeshRenderer>().sharedMaterial = model.material;
309  return true;
310  }
311  }
312 
313  return false;
314  }
315 
316  RenderModel LoadRenderModel(CVRRenderModels renderModels, string renderModelName, string baseName)
317  {
318  var pRenderModel = System.IntPtr.Zero;
319 
320  EVRRenderModelError error;
321  while ( true )
322  {
323  error = renderModels.LoadRenderModel_Async(renderModelName, ref pRenderModel);
324  if (error != EVRRenderModelError.Loading)
325  break;
326 
327  Sleep();
328  }
329 
330  if (error != EVRRenderModelError.None)
331  {
332  Debug.LogError(string.Format("Failed to load render model {0} - {1}", renderModelName, error.ToString()));
333  return null;
334  }
335 
336  var renderModel = MarshalRenderModel(pRenderModel);
337 
338  var vertices = new Vector3[renderModel.unVertexCount];
339  var normals = new Vector3[renderModel.unVertexCount];
340  var uv = new Vector2[renderModel.unVertexCount];
341 
342  var type = typeof(RenderModel_Vertex_t);
343  for (int iVert = 0; iVert < renderModel.unVertexCount; iVert++)
344  {
345  var ptr = new System.IntPtr(renderModel.rVertexData.ToInt64() + iVert * Marshal.SizeOf(type));
346  var vert = (RenderModel_Vertex_t)Marshal.PtrToStructure(ptr, type);
347 
348  vertices[iVert] = new Vector3(vert.vPosition.v0, vert.vPosition.v1, -vert.vPosition.v2);
349  normals[iVert] = new Vector3(vert.vNormal.v0, vert.vNormal.v1, -vert.vNormal.v2);
350  uv[iVert] = new Vector2(vert.rfTextureCoord0, vert.rfTextureCoord1);
351  }
352 
353  int indexCount = (int)renderModel.unTriangleCount * 3;
354  var indices = new short[indexCount];
355  Marshal.Copy(renderModel.rIndexData, indices, 0, indices.Length);
356 
357  var triangles = new int[indexCount];
358  for (int iTri = 0; iTri < renderModel.unTriangleCount; iTri++)
359  {
360  triangles[iTri * 3 + 0] = (int)indices[iTri * 3 + 2];
361  triangles[iTri * 3 + 1] = (int)indices[iTri * 3 + 1];
362  triangles[iTri * 3 + 2] = (int)indices[iTri * 3 + 0];
363  }
364 
365  var mesh = new Mesh();
366  mesh.vertices = vertices;
367  mesh.normals = normals;
368  mesh.uv = uv;
369  mesh.triangles = triangles;
370 
371 #if (UNITY_5_4 || UNITY_5_3 || UNITY_5_2 || UNITY_5_1 || UNITY_5_0)
372  mesh.Optimize();
373 #endif
374  //mesh.hideFlags = HideFlags.DontUnloadUnusedAsset;
375 
376  // Check cache before loading texture.
377  var material = materials[renderModel.diffuseTextureId] as Material;
378  if (material == null || material.mainTexture == null)
379  {
380  var pDiffuseTexture = System.IntPtr.Zero;
381 
382  while (true)
383  {
384  error = renderModels.LoadTexture_Async(renderModel.diffuseTextureId, ref pDiffuseTexture);
385  if (error != EVRRenderModelError.Loading)
386  break;
387 
388  Sleep();
389  }
390 
391  if (error == EVRRenderModelError.None)
392  {
393  var diffuseTexture = MarshalRenderModel_TextureMap(pDiffuseTexture);
394  var texture = new Texture2D(diffuseTexture.unWidth, diffuseTexture.unHeight, TextureFormat.RGBA32, false);
395  if (SystemInfo.graphicsDeviceType == UnityEngine.Rendering.GraphicsDeviceType.Direct3D11)
396  {
397  texture.Apply();
398 
399  while (true)
400  {
401  error = renderModels.LoadIntoTextureD3D11_Async(renderModel.diffuseTextureId, texture.GetNativeTexturePtr());
402  if (error != EVRRenderModelError.Loading)
403  break;
404 
405  Sleep();
406  }
407  }
408  else
409  {
410  var textureMapData = new byte[diffuseTexture.unWidth * diffuseTexture.unHeight * 4]; // RGBA
411  Marshal.Copy(diffuseTexture.rubTextureMapData, textureMapData, 0, textureMapData.Length);
412 
413  var colors = new Color32[diffuseTexture.unWidth * diffuseTexture.unHeight];
414  int iColor = 0;
415  for (int iHeight = 0; iHeight < diffuseTexture.unHeight; iHeight++)
416  {
417  for (int iWidth = 0; iWidth < diffuseTexture.unWidth; iWidth++)
418  {
419  var r = textureMapData[iColor++];
420  var g = textureMapData[iColor++];
421  var b = textureMapData[iColor++];
422  var a = textureMapData[iColor++];
423  colors[iHeight * diffuseTexture.unWidth + iWidth] = new Color32(r, g, b, a);
424  }
425  }
426 
427  texture.SetPixels32(colors);
428  texture.Apply();
429  }
430 
431  material = new Material(shader != null ? shader : Shader.Find("Standard"));
432  material.mainTexture = texture;
433  //material.hideFlags = HideFlags.DontUnloadUnusedAsset;
434 
435  materials[renderModel.diffuseTextureId] = material;
436 
437  renderModels.FreeTexture(pDiffuseTexture);
438  }
439  else
440  {
441  Debug.Log("Failed to load render model texture for render model " + renderModelName);
442  }
443  }
444 
445  // Delay freeing when we can since we'll often get multiple requests for the same model right
446  // after another (e.g. two controllers or two basestations).
447 #if UNITY_EDITOR
448  if (!Application.isPlaying)
449  renderModels.FreeRenderModel(pRenderModel);
450  else
451 #endif
452  StartCoroutine(FreeRenderModel(pRenderModel));
453 
454  return new RenderModel(mesh, material);
455  }
456 
457  IEnumerator FreeRenderModel(System.IntPtr pRenderModel)
458  {
459  yield return new WaitForSeconds(1.0f);
460 
461  using (var holder = new RenderModelInterfaceHolder())
462  {
463  var renderModels = holder.instance;
464  renderModels.FreeRenderModel(pRenderModel);
465  }
466  }
467 
468  public Transform FindComponent(string componentName)
469  {
470  var t = transform;
471  for (int i = 0; i < t.childCount; i++)
472  {
473  var child = t.GetChild(i);
474  if (child.name == componentName)
475  return child;
476  }
477  return null;
478  }
479 
480  private void StripMesh(GameObject go)
481  {
482  var meshRenderer = go.GetComponent<MeshRenderer>();
483  if (meshRenderer != null)
484  DestroyImmediate(meshRenderer);
485 
486  var meshFilter = go.GetComponent<MeshFilter>();
487  if (meshFilter != null)
488  DestroyImmediate(meshFilter);
489  }
490 
491  private bool LoadComponents(RenderModelInterfaceHolder holder, string renderModelName)
492  {
493  // Disable existing components (we will re-enable them if referenced by this new model).
494  // Also strip mesh filter and renderer since these will get re-added if the new component needs them.
495  var t = transform;
496  for (int i = 0; i < t.childCount; i++)
497  {
498  var child = t.GetChild(i);
499  child.gameObject.SetActive(false);
500  StripMesh(child.gameObject);
501  }
502 
503  // If no model specified, we're done; return success.
504  if (string.IsNullOrEmpty(renderModelName))
505  return true;
506 
507  var renderModels = holder.instance;
508  if (renderModels == null)
509  return false;
510 
511  var count = renderModels.GetComponentCount(renderModelName);
512  if (count == 0)
513  return false;
514 
515  for (int i = 0; i < count; i++)
516  {
517  var capacity = renderModels.GetComponentName(renderModelName, (uint)i, null, 0);
518  if (capacity == 0)
519  continue;
520 
521  var componentName = new System.Text.StringBuilder((int)capacity);
522  if (renderModels.GetComponentName(renderModelName, (uint)i, componentName, capacity) == 0)
523  continue;
524 
525  // Create (or reuse) a child object for this component (some components are dynamic and don't have meshes).
526  t = FindComponent(componentName.ToString());
527  if (t != null)
528  {
529  t.gameObject.SetActive(true);
530  }
531  else
532  {
533  t = new GameObject(componentName.ToString()).transform;
534  t.parent = transform;
535  t.gameObject.layer = gameObject.layer;
536 
537  // Also create a child 'attach' object for attaching things.
538  var attach = new GameObject(k_localTransformName).transform;
539  attach.parent = t;
540  attach.localPosition = Vector3.zero;
541  attach.localRotation = Quaternion.identity;
542  attach.localScale = Vector3.one;
543  attach.gameObject.layer = gameObject.layer;
544  }
545 
546  // Reset transform.
547  t.localPosition = Vector3.zero;
548  t.localRotation = Quaternion.identity;
549  t.localScale = Vector3.one;
550 
551  capacity = renderModels.GetComponentRenderModelName(renderModelName, componentName.ToString(), null, 0);
552  if (capacity == 0)
553  continue;
554 
555  var componentRenderModelName = new System.Text.StringBuilder((int)capacity);
556  if (renderModels.GetComponentRenderModelName(renderModelName, componentName.ToString(), componentRenderModelName, capacity) == 0)
557  continue;
558 
559  // Check the cache or load into memory.
560  var model = models[componentRenderModelName] as RenderModel;
561  if (model == null || model.mesh == null)
562  {
563  if (verbose)
564  Debug.Log("Loading render model " + componentRenderModelName);
565 
566  model = LoadRenderModel(renderModels, componentRenderModelName.ToString(), renderModelName);
567  if (model == null)
568  continue;
569 
570  models[componentRenderModelName] = model;
571  }
572 
573  t.gameObject.AddComponent<MeshFilter>().mesh = model.mesh;
574  t.gameObject.AddComponent<MeshRenderer>().sharedMaterial = model.material;
575  }
576 
577  return true;
578  }
579 
580  SteamVR_Events.Action deviceConnectedAction, hideRenderModelsAction, modelSkinSettingsHaveChangedAction;
581 
583  {
584  deviceConnectedAction = SteamVR_Events.DeviceConnectedAction(OnDeviceConnected);
585  hideRenderModelsAction = SteamVR_Events.HideRenderModelsAction(OnHideRenderModels);
586  modelSkinSettingsHaveChangedAction = SteamVR_Events.SystemAction(EVREventType.VREvent_ModelSkinSettingsHaveChanged, OnModelSkinSettingsHaveChanged);
587  }
588 
589  void OnEnable()
590  {
591 #if UNITY_EDITOR
592  if (!Application.isPlaying)
593  return;
594 #endif
595  if (!string.IsNullOrEmpty(modelOverride))
596  {
597  Debug.Log(modelOverrideWarning);
598  enabled = false;
599  return;
600  }
601 
602  var system = OpenVR.System;
603  if (system != null && system.IsTrackedDeviceConnected((uint)index))
604  {
605  UpdateModel();
606  }
607 
608  deviceConnectedAction.enabled = true;
609  hideRenderModelsAction.enabled = true;
610  modelSkinSettingsHaveChangedAction.enabled = true;
611  }
612 
613  void OnDisable()
614  {
615 #if UNITY_EDITOR
616  if (!Application.isPlaying)
617  return;
618 #endif
619  deviceConnectedAction.enabled = false;
620  hideRenderModelsAction.enabled = false;
621  modelSkinSettingsHaveChangedAction.enabled = false;
622  }
623 
624 #if UNITY_EDITOR
625  Hashtable values;
626 #endif
627  void Update()
628  {
629 #if UNITY_EDITOR
630  if (!Application.isPlaying)
631  {
632  // See if anything has changed since this gets called whenever anything gets touched.
633  var fields = GetType().GetFields(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
634 
635  bool modified = false;
636 
637  if (values == null)
638  {
639  modified = true;
640  }
641  else
642  {
643  foreach (var f in fields)
644  {
645  if (!values.Contains(f))
646  {
647  modified = true;
648  break;
649  }
650 
651  var v0 = values[f];
652  var v1 = f.GetValue(this);
653  if (v1 != null)
654  {
655  if (!v1.Equals(v0))
656  {
657  modified = true;
658  break;
659  }
660  }
661  else if (v0 != null)
662  {
663  modified = true;
664  break;
665  }
666  }
667  }
668 
669  if (modified)
670  {
671  if (renderModelName != modelOverride)
672  {
673  renderModelName = modelOverride;
674  SetModel(modelOverride);
675  }
676 
677  values = new Hashtable();
678  foreach (var f in fields)
679  values[f] = f.GetValue(this);
680  }
681 
682  return; // Do not update transforms (below) when not playing in Editor (to avoid keeping OpenVR running all the time).
683  }
684 #endif
685  // Update component transforms dynamically.
686  if (updateDynamically)
687  UpdateComponents(OpenVR.RenderModels);
688  }
689 
690  Dictionary<int, string> nameCache;
691 
692  public void UpdateComponents(CVRRenderModels renderModels)
693  {
694  if (renderModels == null)
695  return;
696 
697  var t = transform;
698  if (t.childCount == 0)
699  return;
700 
701  var controllerState = (index != SteamVR_TrackedObject.EIndex.None) ?
702  SteamVR_Controller.Input((int)index).GetState() : new VRControllerState_t();
703 
704  if (nameCache == null)
705  nameCache = new Dictionary<int, string>();
706 
707  for (int i = 0; i < t.childCount; i++)
708  {
709  var child = t.GetChild(i);
710 
711  // Cache names since accessing an object's name allocate memory.
712  string name;
713  if (!nameCache.TryGetValue(child.GetInstanceID(), out name))
714  {
715  name = child.name;
716  nameCache.Add(child.GetInstanceID(), name);
717  }
718 
719  var componentState = new RenderModel_ComponentState_t();
720  if (!renderModels.GetComponentState(renderModelName, name, ref controllerState, ref controllerModeState, ref componentState))
721  continue;
722 
723  var componentTransform = new SteamVR_Utils.RigidTransform(componentState.mTrackingToComponentRenderModel);
724  child.localPosition = componentTransform.pos;
725  child.localRotation = componentTransform.rot;
726 
727  var attach = child.Find(k_localTransformName);
728  if (attach != null)
729  {
730  var attachTransform = new SteamVR_Utils.RigidTransform(componentState.mTrackingToComponentLocal);
731  attach.position = t.TransformPoint(attachTransform.pos);
732  attach.rotation = t.rotation * attachTransform.rot;
733  }
734 
735  bool visible = (componentState.uProperties & (uint)EVRComponentProperty.IsVisible) != 0;
736  if (visible != child.gameObject.activeSelf)
737  {
738  child.gameObject.SetActive(visible);
739  }
740  }
741  }
742 
743  public void SetDeviceIndex(int index)
744  {
745  this.index = (SteamVR_TrackedObject.EIndex)index;
746  modelOverride = "";
747 
748  if (enabled)
749  {
750  UpdateModel();
751  }
752  }
753 
754  private static void Sleep()
755  {
756 #if !UNITY_METRO
757  System.Threading.Thread.Sleep(1);
758 #endif
759  }
760 
767  private RenderModel_t MarshalRenderModel(System.IntPtr pRenderModel)
768  {
769  if ((System.Environment.OSVersion.Platform == System.PlatformID.MacOSX) ||
770  (System.Environment.OSVersion.Platform == System.PlatformID.Unix))
771  {
772  var packedModel = (RenderModel_t_Packed)Marshal.PtrToStructure(pRenderModel, typeof(RenderModel_t_Packed));
773  RenderModel_t model = new RenderModel_t();
774  packedModel.Unpack(ref model);
775  return model;
776  }
777  else
778  {
779  return (RenderModel_t)Marshal.PtrToStructure(pRenderModel, typeof(RenderModel_t));
780  }
781  }
782 
789  private RenderModel_TextureMap_t MarshalRenderModel_TextureMap(System.IntPtr pRenderModel)
790  {
791  if ((System.Environment.OSVersion.Platform == System.PlatformID.MacOSX) ||
792  (System.Environment.OSVersion.Platform == System.PlatformID.Unix))
793  {
794  var packedModel = (RenderModel_TextureMap_t_Packed)Marshal.PtrToStructure(pRenderModel, typeof(RenderModel_TextureMap_t_Packed));
796  packedModel.Unpack(ref model);
797  return model;
798  }
799  else
800  {
801  return (RenderModel_TextureMap_t)Marshal.PtrToStructure(pRenderModel, typeof(RenderModel_TextureMap_t));
802  }
803  }
804 }
805