private void ReadMesh(ref XmlReadState state, System.Xml.XmlReader node) { node.Read(); var P = node.GetAttribute("P"); var UV = node.GetAttribute("UV"); var nverts = node.GetAttribute("nverts"); var verts = node.GetAttribute("verts"); if(!state.Silent) Console.WriteLine("{0}", node); var has_uv = !string.IsNullOrEmpty(UV); float[] uvfloats = null; if (has_uv) { uvfloats = Utilities.Instance.parse_floats(UV); } var pfloats = Utilities.Instance.parse_floats(P); var nvertsints = Utilities.Instance.parse_ints(nverts); var vertsints = Utilities.Instance.parse_ints(verts); var ob = new ccl.Object(Client) { Transform = state.Transform }; var me = new Mesh(Client, state.Shader); ob.Mesh = me; me.SetVerts(ref pfloats); var index_offset = 0; /* count triangles */ var fc = nvertsints.Aggregate(0, (total, next) => next == 4 ? total + 2 : total + 1); float[] uvs = null; if(has_uv) uvs = new float[fc*3*2]; var uvoffs = 0; foreach (var t in nvertsints) { for (var j = 0; j < t - 2; j++) { var v0 = vertsints[index_offset]; var v1 = vertsints[index_offset + j + 1]; var v2 = vertsints[index_offset + j + 2]; if (has_uv) { uvs[uvoffs] = uvfloats[index_offset*2]; uvs[uvoffs + 1] = uvfloats[index_offset*2 + 1]; uvs[uvoffs + 2] = uvfloats[(index_offset + j + 1)*2]; uvs[uvoffs + 3] = uvfloats[(index_offset + j + 1)*2 + 1]; uvs[uvoffs + 4] = uvfloats[(index_offset + j + 2)*2]; uvs[uvoffs + 5] = uvfloats[(index_offset + j + 2)*2 + 1]; uvoffs += 6; } me.AddTri((uint)v0, (uint)v1, (uint)v2, state.Shader, state.Smooth); } index_offset += t; } if (has_uv) { me.SetUvs(ref uvs); } }
/// <summary> /// Upload mesh changes /// </summary> public void UploadMeshChanges() { // handle mesh deletes first foreach (var meshDelete in _objectDatabase.MeshesToDelete) { var cobs = _objectDatabase.GetCyclesObjectsForGuid(meshDelete); foreach (var cob in cobs) { // remove mesh data cob.Mesh.ClearData(); cob.Mesh.TagRebuild(); // hide object containing the mesh cob.Visibility = PathRay.Hidden; cob.TagUpdate(); } } var curmesh = 0; var totalmeshes = _objectDatabase.MeshChanges.Count; foreach (var meshChange in _objectDatabase.MeshChanges) { var cyclesMesh = meshChange.Value; var mid = meshChange.Key; var me = _objectDatabase.FindMeshRelation(mid); // newme true if we have to upload new mesh data var newme = me == null; if (_renderEngine.CancelRender) return; // lets find the shader for this, or use 0 if none found. uint shid; var matid = _objectShaderDatabase.FindRenderHashForMeshId(cyclesMesh.MeshId); try { // @todo check this is correct naming and dictionary to query from shid = _shaderDatabase.GetShaderIdForMatId(matid); } catch (Exception) { shid = 0; } var shader = _renderEngine.Client.Scene.ShaderFromSceneId(shid); // creat a new mesh to upload mesh data to if (newme) { me = new CclMesh(_renderEngine.Client, shader); } me.Resize((uint)cyclesMesh.verts.Length/3, (uint)cyclesMesh.faces.Length/3); // update status bar of render window. var stat = $"Upload mesh {curmesh}/{totalmeshes} [v: {cyclesMesh.verts.Length}, t: {cyclesMesh.faces.Length} using shader {shid}]"; // set progress, but without rendering percentage (hence the -1.0f) _renderEngine.SetProgress(_renderEngine.RenderWindow, stat, -1.0f); // upload, if we get false back we were signalled to stop rendering by user if (!UploadMeshData(me, cyclesMesh)) return; // if we re-uploaded mesh data, we need to make sure the shader // information doesn't get lost. if (!newme) me.ReplaceShader(shader); // don't forget to record this new mesh if(newme) _objectDatabase.RecordObjectMeshRelation(cyclesMesh.MeshId, me); //RecordShaderRelation(shader, cycles_mesh.MeshId); curmesh++; } }