//-------------------------------- private void WalkNodeHierarchy(TreeNodeAdv parentTreeNode, ModelNode node) { // add the current node to the tree. TreeNodeAdv curTreeNode = new TreeNodeAdv(node.Name); parentTreeNode.Nodes.Add(curTreeNode); // now add mesh instances to the tree. int meshInstCount = node.MeshInstCount; for (int i = 0; i < meshInstCount; ++i) { // add the instance. MeshInst inst = node.GetMeshInst(i); TreeNodeAdv curMeshNode = new TreeNodeAdv("< mesh >"); curTreeNode.Nodes.Add(curMeshNode); // add the instance's ranges. Mesh mesh = inst.Mesh; for (int j = 0; j < inst.RangeCount; ++j) { // get the range info. RangeInfo range; if (!mesh.GetRange(out range, j)) { continue; } // get the material assignend to that range. Material material = inst.GetMaterial(j); if (material == null) { continue; } // add the name of the range. TreeNodeAdv curRangeNode = new TreeNodeAdv(range.Name); curMeshNode.Nodes.Add(curRangeNode); // add the range's material. TreeNodeAdv curMatNode = new TreeNodeAdv(material.Name); curRangeNode.Nodes.Add(curMatNode); // add statistics. TreeNodeAdv curTriCountNode = new TreeNodeAdv(range.Count.ToString() + " tris"); curRangeNode.Nodes.Add(curTriCountNode); } } // recurse children. int childCount = node.ChildCount; for (int i = 0; i < childCount; ++i) { WalkNodeHierarchy(curTreeNode, node.GetChild(i)); } }
//-------------------------------- private void AddUberizeItem(TreeNodeAdv parent, MeshInst inst) { TreeNodeAdv meshNode = new TreeNodeAdv(inst.Mesh.Name); parent.Nodes.Add(meshNode); // iterate through mesh instance's ranges. int rangeIndex = 0; Mesh mesh = inst.Mesh; for (int i = 0; i < inst.RangeCount; ++i) { // get the range info. RangeInfo range; if (!mesh.GetRange(out range, i)) { continue; } TreeNodeAdv rangeNode = new TreeNodeAdv(range.Name); meshNode.Nodes.Add(rangeNode); // fill out a new key. MeshInstRange key = new MeshInstRange(); key.inst = inst; key.range = rangeIndex; // check for the current mesh instance/range pair. if (_uberizeItems.ContainsKey(key)) { // increment the reference count if necessary. _uberizeItems[key] += 1; } else { // TODO: Calculate a valid default matrix. _uberizeItems.Add(key, 1); rangeNode.Tag = key; } } }
static void ExportObj() { var obj = Selection.activeGameObject; if (obj == null) { return; } List <MeshInst> meshs = new List <MeshInst>(); var ms = obj.GetComponentsInChildren <MeshRenderer>(); for (int i = 0; i < ms.Length; i++) { var mats = ms[i].sharedMaterials; var mf = ms[i].GetComponent <MeshFilter>(); if (mf != null && mf.sharedMesh != null) { MeshInst inst = new MeshInst(); inst.obj = ms[i].gameObject; inst.mats = mats; inst.texs = new Texture2D[mats.Length]; for (int j = 0; j < mats.Length; j++) { if (mats[j] != null) { inst.texs[j] = mats[j].mainTexture as Texture2D; } } inst.mesh = mf.sharedMesh; inst.vertices = inst.mesh.vertices; inst.uv = inst.mesh.uv; inst.normals = inst.mesh.normals; inst.submeshs = new List <int[]>(); for (int j = 0; j < inst.mesh.subMeshCount; j++) { inst.submeshs.Add(inst.mesh.GetIndices(j)); } meshs.Add(inst); } } StringBuilder sb = new StringBuilder(); for (int i = 0; i < meshs.Count; i++) { var inst = meshs[i]; for (int j = 0; j < inst.vertices.Length; j++) { var pos = inst.vertices[j]; pos = inst.obj.transform.localToWorldMatrix.MultiplyPoint3x4(pos); sb.AppendFormat("v {0} {1} {2}\r\n", -pos.x, pos.y, pos.z); } if (i == 0) { inst.startIndex = 0; } else { inst.startIndex = meshs[i - 1].startIndex + meshs[i - 1].vertices.Length; } } for (int i = 0; i < meshs.Count; i++) { var inst = meshs[i]; for (int j = 0; j < inst.uv.Length; j++) { var uv = inst.uv[j]; sb.AppendFormat("vt {0} {1}\r\n", uv.x, uv.y); } } for (int i = 0; i < meshs.Count; i++) { var inst = meshs[i]; for (int j = 0; j < inst.normals.Length; j++) { var nor = inst.normals[j]; sb.AppendFormat("vn {0} {1} {2}\r\n", -nor.x, nor.y, nor.z); } } sb.Append("mtllib scene.mtl\r\n"); for (int i = 0; i < meshs.Count; i++) { var inst = meshs[i]; for (int j = 0; j < inst.submeshs.Count; j++) { var indices = inst.submeshs[j]; sb.AppendFormat("g group_{0}_{1}\r\n", i, j); sb.AppendFormat("usemtl mat_{0}_{1}\r\n", i, j); for (int k = 0; k < indices.Length; k += 3) { var i0 = indices[k]; var i1 = indices[k + 2]; var i2 = indices[k + 1]; sb.AppendFormat("f {0}/{0}/{0} {1}/{1}/{1} {2}/{2}/{2}\r\n", inst.startIndex + i0 + 1, inst.startIndex + i1 + 1, inst.startIndex + i2 + 1); } } } if (!Directory.Exists("scene_obj_export")) { Directory.CreateDirectory("scene_obj_export"); } File.WriteAllText("Assets/scene.obj", sb.ToString()); sb = new StringBuilder(); for (int i = 0; i < meshs.Count; i++) { var inst = meshs[i]; for (int j = 0; j < inst.texs.Length; j++) { if (inst.texs[j] != null) { var path = AssetDatabase.GetAssetPath(inst.texs[j]); var name = new FileInfo(path).Name; if (!File.Exists("scene_obj_export/" + name)) { File.Copy(path, "scene_obj_export/" + name, false); } sb.AppendFormat("newmtl mat_{0}_{1}\r\n", i, j); sb.Append("Kd 1.000 1.000 1.000\r\n"); sb.AppendFormat("map_Kd {0}\r\n", name); } } } File.WriteAllText("Assets/scene.mtl", sb.ToString()); Debug.Log("export done."); }
//----------------------- public void Paint(MeshInst meshInst, int rangeIdx, uint[] triangleMask, PaintMode paintMode) { if (meshInst == null) { return; } Mesh mesh = meshInst.Mesh; if (mesh == null) { return; } // get the material associated with the meshInst's range. Material material = meshInst.GetMaterial(rangeIdx); if (material == null) { return; } // if the material isn't ubertextured, skip it. if (!material.Ubertextured) { return; } // determine if the current range and the paint frustum // intersect. if (!_maskCamera.Frustum.IsOBoxInside(meshInst.GetRangeOBox(rangeIdx))) { return; } // configure the ubertexture renderer for the current material's // targets. UberTexture uberTexture = new UberTexture(material.GetPass(0).UberTexture); if (uberTexture == null) { return; } _target = uberTexture; // get the inverse of the mesh instance's transform. This is // so we can move the cameras into the mesh instance's local // space for culling and rasterization purposes. Matrix invInstXForm = new Matrix(); if (!meshInst.Transform.Inverse(out invInstXForm)) { return; } // get the source camera's transform. Matrix sourceCamXForm = new Matrix(_sourceCamera.Rotation, _sourceCamera.Position); Matrix maskCamXForm = new Matrix(_maskCamera.Rotation, _maskCamera.Position); sourceCamXForm = invInstXForm * sourceCamXForm; maskCamXForm = invInstXForm * maskCamXForm; // build cameras that are local to the mesh instance. Camera localSourceCamera = new Camera(sourceCamXForm.Translate, sourceCamXForm.Rotate, _sourceCamera.Projection); Camera localMaskCamera = new Camera(maskCamXForm.Translate, maskCamXForm.Rotate, _maskCamera.Projection); // set the paint targets. _rasterizer.RenderTarget = _target; // set the camera info. _rasterizer.SetVertexConstants(0, localSourceCamera.ViewProjMatrix); _rasterizer.SetVertexConstants(4, localMaskCamera.ViewProjMatrix); // set the blending mode to accumulate. float blendingMode = 1.0f; if (_maskPaintMode == MaskMode.Subtract) { blendingMode = 0.0f; } // if the paint mode is 'fill' then disable the per-pixel clip. float perPixelClip = 1.0f; if (paintMode == PaintMode.Fill) { perPixelClip = 0.0f; } // set the mask-only value. float maskValue = 0.0f; if (paintMode == PaintMode.Mask) { maskValue = 1.0f; } // setup the shader modes. _rasterizer.SetFragmentConstant(0, new Vector4(blendingMode, perPixelClip, maskValue, 0.0f)); // set the camera's rotation for normals. Matrix cameraRot = new Matrix(localSourceCamera.Rotation, new Vector3(0.0f, 0.0f, 0.0f)); _rasterizer.SetFragmentConstants(1, cameraRot); // now grab the mesh's vertices and throw them at the // uber-texture renderer. uint triCount = CalculateVisibleTriangles(localMaskCamera, meshInst.Mesh, rangeIdx); // now render the visible triangles. _rasterizer.RenderTriangleList(meshInst.Mesh.VertexBuffer, _visibleTriangles, 0, 3 * triCount); }