RenderModel LoadRenderModel(CVRRenderModels renderModels, string renderModelName, string baseName) { var pRenderModel = System.IntPtr.Zero; EVRRenderModelError error; while (true) { error = renderModels.LoadRenderModel_Async(renderModelName, ref pRenderModel); if (error != EVRRenderModelError.Loading) { break; } System.Threading.Thread.Sleep(1); } if (error != EVRRenderModelError.None) { Debug.LogError(string.Format("Failed to load render model {0} - {1}", renderModelName, error.ToString())); return(null); } var renderModel = (RenderModel_t)Marshal.PtrToStructure(pRenderModel, typeof(RenderModel_t)); var vertices = new Vector3[renderModel.unVertexCount]; var normals = new Vector3[renderModel.unVertexCount]; var uv = new Vector2[renderModel.unVertexCount]; var type = typeof(RenderModel_Vertex_t); for (int iVert = 0; iVert < renderModel.unVertexCount; iVert++) { var ptr = new System.IntPtr(renderModel.rVertexData.ToInt64() + iVert * Marshal.SizeOf(type)); var vert = (RenderModel_Vertex_t)Marshal.PtrToStructure(ptr, type); vertices[iVert] = new Vector3(vert.vPosition.v0, vert.vPosition.v1, -vert.vPosition.v2); normals[iVert] = new Vector3(vert.vNormal.v0, vert.vNormal.v1, -vert.vNormal.v2); uv[iVert] = new Vector2(vert.rfTextureCoord0, vert.rfTextureCoord1); } int indexCount = (int)renderModel.unTriangleCount * 3; var indices = new short[indexCount]; Marshal.Copy(renderModel.rIndexData, indices, 0, indices.Length); var triangles = new int[indexCount]; for (int iTri = 0; iTri < renderModel.unTriangleCount; iTri++) { triangles[iTri * 3 + 0] = (int)indices[iTri * 3 + 2]; triangles[iTri * 3 + 1] = (int)indices[iTri * 3 + 1]; triangles[iTri * 3 + 2] = (int)indices[iTri * 3 + 0]; } var mesh = new Mesh(); mesh.vertices = vertices; mesh.normals = normals; mesh.uv = uv; mesh.triangles = triangles; #if (UNITY_5_4 || UNITY_5_3 || UNITY_5_2 || UNITY_5_1 || UNITY_5_0) mesh.Optimize(); #endif //mesh.hideFlags = HideFlags.DontUnloadUnusedAsset; // Check cache before loading texture. var material = materials[renderModel.diffuseTextureId] as Material; if (material == null || material.mainTexture == null) { var pDiffuseTexture = System.IntPtr.Zero; while (true) { error = renderModels.LoadTexture_Async(renderModel.diffuseTextureId, ref pDiffuseTexture); if (error != EVRRenderModelError.Loading) { break; } System.Threading.Thread.Sleep(1); } if (error == EVRRenderModelError.None) { var diffuseTexture = (RenderModel_TextureMap_t)Marshal.PtrToStructure(pDiffuseTexture, typeof(RenderModel_TextureMap_t)); var texture = new Texture2D(diffuseTexture.unWidth, diffuseTexture.unHeight, TextureFormat.ARGB32, false); if (SystemInfo.graphicsDeviceType == UnityEngine.Rendering.GraphicsDeviceType.Direct3D11) { texture.Apply(); while (true) { error = renderModels.LoadIntoTextureD3D11_Async(renderModel.diffuseTextureId, texture.GetNativeTexturePtr()); if (error != EVRRenderModelError.Loading) { break; } System.Threading.Thread.Sleep(1); } } else { var textureMapData = new byte[diffuseTexture.unWidth * diffuseTexture.unHeight * 4]; // RGBA Marshal.Copy(diffuseTexture.rubTextureMapData, textureMapData, 0, textureMapData.Length); var colors = new Color32[diffuseTexture.unWidth * diffuseTexture.unHeight]; int iColor = 0; for (int iHeight = 0; iHeight < diffuseTexture.unHeight; iHeight++) { for (int iWidth = 0; iWidth < diffuseTexture.unWidth; iWidth++) { var r = textureMapData[iColor++]; var g = textureMapData[iColor++]; var b = textureMapData[iColor++]; var a = textureMapData[iColor++]; colors[iHeight * diffuseTexture.unWidth + iWidth] = new Color32(r, g, b, a); } } texture.SetPixels32(colors); texture.Apply(); } material = new Material(shader != null ? shader : Shader.Find("Standard")); material.mainTexture = texture; //material.hideFlags = HideFlags.DontUnloadUnusedAsset; materials[renderModel.diffuseTextureId] = material; renderModels.FreeTexture(pDiffuseTexture); } else { Debug.Log("Failed to load render model texture for render model " + renderModelName); } } // Delay freeing when we can since we'll often get multiple requests for the same model right // after another (e.g. two controllers or two basestations). #if UNITY_EDITOR if (!Application.isPlaying) { renderModels.FreeRenderModel(pRenderModel); } else #endif StartCoroutine(FreeRenderModel(pRenderModel)); return(new RenderModel(mesh, material)); }
public void UpdateComponents(CVRRenderModels renderModels) { if (renderModels == null) { return; } var t = transform; if (t.childCount == 0) { return; } var controllerState = (index != SteamVR_TrackedObject.EIndex.None) ? SteamVR_Controller.Input((int)index).GetState() : new VRControllerState_t(); if (nameCache == null) { nameCache = new Dictionary <int, string>(); } for (int i = 0; i < t.childCount; i++) { var child = t.GetChild(i); // Cache names since accessing an object's name allocate memory. string name; if (!nameCache.TryGetValue(child.GetInstanceID(), out name)) { name = child.name; nameCache.Add(child.GetInstanceID(), name); } var componentState = new RenderModel_ComponentState_t(); if ( !renderModels.GetComponentState(renderModelName, name, ref controllerState, ref controllerModeState, ref componentState)) { continue; } var componentTransform = new SteamVR_Utils.RigidTransform(componentState.mTrackingToComponentRenderModel); child.localPosition = componentTransform.pos; child.localRotation = componentTransform.rot; var attach = child.Find(k_localTransformName); if (attach != null) { var attachTransform = new SteamVR_Utils.RigidTransform(componentState.mTrackingToComponentLocal); attach.position = t.TransformPoint(attachTransform.pos); attach.rotation = t.rotation * attachTransform.rot; } bool visible = (componentState.uProperties & (uint)EVRComponentProperty.IsVisible) != 0; if (visible != child.gameObject.activeSelf) { child.gameObject.SetActive(visible); } } }
// return true if is done private bool DoLoadModelJob(CVRRenderModels vrRenderModels, string modelName, Dictionary <int, Texture2D> texturesCache, ref IntPtr modelPtr, ref IntPtr texturePtr, ref IntPtr d3d11TexturePtr) { if (string.IsNullOrEmpty(modelName)) { return(true); } EVRRenderModelError error; Model model; if (!s_modelsCache.TryGetValue(modelName, out model)) { switch (error = vrRenderModels.LoadRenderModel_Async(modelName, ref modelPtr)) { default: Debug.LogError("[" + m_jobID + "]+" + (Time.frameCount - m_startFrame) + " LoadRenderModel_Async failed! " + System.IO.Path.GetFileName(modelName) + " EVRRenderModelError=" + error); return(true); case EVRRenderModelError.Loading: if (s_verbose) { Debug.Log("[" + m_jobID + "]+" + (Time.frameCount - m_startFrame) + " LoadRenderModel_Async loading... " + System.IO.Path.GetFileName(modelName)); } return(false); case EVRRenderModelError.None: if (s_verbose) { Debug.Log("[" + m_jobID + "]+" + (Time.frameCount - m_startFrame) + " LoadRenderModel_Async succeed! " + System.IO.Path.GetFileName(modelName)); } RenderModel_t modelData = MarshalRenderModel(modelPtr); var vertices = new Vector3[modelData.unVertexCount]; var normals = new Vector3[modelData.unVertexCount]; var uv = new Vector2[modelData.unVertexCount]; Type type = typeof(RenderModel_Vertex_t); for (int iVert = 0; iVert < modelData.unVertexCount; iVert++) { var ptr = new IntPtr(modelData.rVertexData.ToInt64() + iVert * Marshal.SizeOf(type)); var vert = (RenderModel_Vertex_t)Marshal.PtrToStructure(ptr, type); vertices[iVert] = new Vector3(vert.vPosition.v0, vert.vPosition.v1, -vert.vPosition.v2); normals[iVert] = new Vector3(vert.vNormal.v0, vert.vNormal.v1, -vert.vNormal.v2); uv[iVert] = new Vector2(vert.rfTextureCoord0, vert.rfTextureCoord1); } var indexCount = (int)modelData.unTriangleCount * 3; var indices = new short[indexCount]; Marshal.Copy(modelData.rIndexData, indices, 0, indices.Length); var triangles = new int[indexCount]; for (int iTri = 0; iTri < modelData.unTriangleCount; iTri++) { triangles[iTri * 3 + 0] = indices[iTri * 3 + 2]; triangles[iTri * 3 + 1] = indices[iTri * 3 + 1]; triangles[iTri * 3 + 2] = indices[iTri * 3 + 0]; } model = new Model() { textureID = modelData.diffuseTextureId, mesh = new Mesh() { hideFlags = HideFlags.HideAndDontSave, vertices = vertices, normals = normals, uv = uv, triangles = triangles, }, }; s_modelsCache.Add(modelName, model); break; } } Texture2D texture; if (!texturesCache.TryGetValue(model.textureID, out texture)) { switch (error = vrRenderModels.LoadTexture_Async(model.textureID, ref texturePtr)) { default: Debug.LogError("[" + m_jobID + "]+" + (Time.frameCount - m_startFrame) + " LoadTexture_Async failed! " + System.IO.Path.GetFileName(modelName) + "[" + model.textureID + "] EVRRenderModelError=" + error); return(true); case EVRRenderModelError.Loading: if (s_verbose) { Debug.Log("[" + m_jobID + "]+" + (Time.frameCount - m_startFrame) + " LoadTexture_Async loading... " + System.IO.Path.GetFileName(modelName) + "[" + model.textureID + "]"); } return(false); case EVRRenderModelError.None: if (s_verbose) { Debug.Log("[" + m_jobID + "]+" + (Time.frameCount - m_startFrame) + " LoadTexture_Async succeed! " + System.IO.Path.GetFileName(modelName) + "[" + model.textureID + "]"); } var textureMap = MarshalRenderModelTextureMap(texturePtr); texture = new Texture2D(textureMap.unWidth, textureMap.unHeight, TextureFormat.RGBA32, false); if (SystemInfo.graphicsDeviceType == GraphicsDeviceType.Direct3D11) { texture.Apply(); d3d11TexturePtr = texture.GetNativeTexturePtr(); } else { var textureMapData = new byte[textureMap.unWidth * textureMap.unHeight * 4]; // RGBA Marshal.Copy(textureMap.rubTextureMapData, textureMapData, 0, textureMapData.Length); var colors = new Color32[textureMap.unWidth * textureMap.unHeight]; int iColor = 0; for (int iHeight = 0; iHeight < textureMap.unHeight; iHeight++) { for (int iWidth = 0; iWidth < textureMap.unWidth; iWidth++) { var r = textureMapData[iColor++]; var g = textureMapData[iColor++]; var b = textureMapData[iColor++]; var a = textureMapData[iColor++]; colors[iHeight * textureMap.unWidth + iWidth] = new Color32(r, g, b, a); } } texture.SetPixels32(colors); texture.Apply(); } texturesCache.Add(model.textureID, texture); break; } } if (d3d11TexturePtr != IntPtr.Zero) { while (true) { switch (error = vrRenderModels.LoadIntoTextureD3D11_Async(model.textureID, d3d11TexturePtr)) { default: Debug.LogError("[" + m_jobID + "]+" + (Time.frameCount - m_startFrame) + " LoadIntoTextureD3D11_Async failed! " + System.IO.Path.GetFileName(modelName) + " EVRRenderModelError=" + error); d3d11TexturePtr = IntPtr.Zero; return(true); case EVRRenderModelError.Loading: if (s_verbose) { Debug.Log("[" + m_jobID + "]+" + (Time.frameCount - m_startFrame) + " LoadIntoTextureD3D11_Async loading... " + System.IO.Path.GetFileName(modelName) + "[" + model.textureID + "]"); } break; case EVRRenderModelError.None: if (s_verbose) { Debug.Log("[" + m_jobID + "]+" + (Time.frameCount - m_startFrame) + " LoadIntoTextureD3D11_Async succeed! " + System.IO.Path.GetFileName(modelName)); } d3d11TexturePtr = IntPtr.Zero; return(true); } // FIXME: LoadIntoTextureD3D11_Async blocks main thread? Crashes when not calling it in while loop #if !UNITY_METRO System.Threading.Thread.Sleep(1); #endif } } return(true); }
static RenderModel LoadRenderModel(CVRRenderModels renderModels, string renderModelName, string baseName) { var pRenderModel = System.IntPtr.Zero; if (!renderModels.LoadRenderModel(renderModelName, ref pRenderModel)) { Debug.LogError("Failed to load render model " + renderModelName); return(null); } var renderModel = (RenderModel_t)Marshal.PtrToStructure(pRenderModel, typeof(RenderModel_t)); var vertices = new Vector3[renderModel.unVertexCount]; var normals = new Vector3[renderModel.unVertexCount]; var uv = new Vector2[renderModel.unVertexCount]; var type = typeof(RenderModel_Vertex_t); for (int iVert = 0; iVert < renderModel.unVertexCount; iVert++) { var ptr = new System.IntPtr(renderModel.rVertexData.ToInt64() + iVert * Marshal.SizeOf(type)); var vert = (RenderModel_Vertex_t)Marshal.PtrToStructure(ptr, type); vertices[iVert] = new Vector3(vert.vPosition.v[0], vert.vPosition.v[1], -vert.vPosition.v[2]); normals[iVert] = new Vector3(vert.vNormal.v[0], vert.vNormal.v[1], -vert.vNormal.v[2]); uv[iVert] = new Vector2(vert.rfTextureCoord[0], vert.rfTextureCoord[1]); } int indexCount = (int)renderModel.unTriangleCount * 3; var indices = new short[indexCount]; Marshal.Copy(renderModel.rIndexData, indices, 0, indices.Length); var triangles = new int[indexCount]; for (int iTri = 0; iTri < renderModel.unTriangleCount; iTri++) { triangles[iTri * 3 + 0] = (int)indices[iTri * 3 + 2]; triangles[iTri * 3 + 1] = (int)indices[iTri * 3 + 1]; triangles[iTri * 3 + 2] = (int)indices[iTri * 3 + 0]; } var mesh = new Mesh(); mesh.vertices = vertices; mesh.normals = normals; mesh.uv = uv; mesh.triangles = triangles; mesh.Optimize(); //mesh.hideFlags = HideFlags.DontUnloadUnusedAsset; // Check cache before loading texture. var material = materials[baseName + renderModel.diffuseTextureId] as Material; if (material == null || material.mainTexture == null) { var pDiffuseTexture = System.IntPtr.Zero; if (renderModels.LoadTexture(renderModel.diffuseTextureId, ref pDiffuseTexture)) { var diffuseTexture = (RenderModel_TextureMap_t)Marshal.PtrToStructure(pDiffuseTexture, typeof(RenderModel_TextureMap_t)); var textureMapData = new byte[diffuseTexture.unWidth * diffuseTexture.unHeight * 4]; // RGBA Marshal.Copy(diffuseTexture.rubTextureMapData, textureMapData, 0, textureMapData.Length); var colors = new Color32[diffuseTexture.unWidth * diffuseTexture.unHeight]; int iColor = 0; for (int iHeight = 0; iHeight < diffuseTexture.unHeight; iHeight++) { for (int iWidth = 0; iWidth < diffuseTexture.unWidth; iWidth++) { var r = textureMapData[iColor++]; var g = textureMapData[iColor++]; var b = textureMapData[iColor++]; var a = textureMapData[iColor++]; colors[iHeight * diffuseTexture.unWidth + iWidth] = new Color32(r, g, b, a); } } var texture = new Texture2D(diffuseTexture.unWidth, diffuseTexture.unHeight, TextureFormat.ARGB32, true); texture.SetPixels32(colors); texture.Apply(); material = new Material(Shader.Find("Standard")); material.mainTexture = texture; //material.hideFlags = HideFlags.DontUnloadUnusedAsset; materials[baseName + renderModel.diffuseTextureId] = material; } else { Debug.Log("Failed to load render model texture for render model " + renderModelName); } } renderModels.FreeRenderModel(ref renderModel); return(new RenderModel(mesh, material)); }