[Unity3D]メッシュCombineMeshesをマージするもの(2)



Those Things That Merge Mesh Combinemeshes



前の期間( https://blog.csdn.net/tw_345/article/details/79771454 )メッシュをいくつか描いただけですが、それらをマージするのは意味がありませんでした。そこで、もう少し深く掘り下げて、マテリアル、マップ、テクスチャといういくつかの概念を紹介しました。単調なメッシュにスキンを持たせる必要があります。一般に、3つの階層関係は次のとおりです。マテリアルにはマップが含まれ、マップにはテクスチャが含まれます。
テクスチャは基本的に、最も基本的なデータ入力ユニットであるゲームフィールドでビットマップを使用します。マップは、UVを介してテクスチャを3Dオブジェクトの表面にマップします(UV座標を除く。マップには、テクスチャ以外の多くの情報も含まれています)。 Materialはデータセットであり、Mapはその一部であり、もう1つの重要な部分はShaderです。これは、カラーリングパイプラインのレンダリング効果を変更するために使用されます。 (よくわからない場合は、まずは理解しましょう)
これらのコンセプトで、私は多くのキャラクターやシーンをレンダリングすることができます。次に、いくつかの概念、アニメーション、ボーンを紹介します。上記の概念を統一して説明するには、以下を参照してください。

https://www.jianshu.com/p/f3f6d4a7940d (Unity3D(1)のマテリアルを作成する:画像、シェーダー、シェーダー)
https://www.jianshu.com/p/e2aa4d898fb7 (Unity3D(2)のマテリアルを作成する:モデル、バインディング、アニメーション)
彼は非常に詳細に書いた。



したがって、メッシュのマージはメッシュを処理するだけでなく、多くの要素を含みます。 githubでドレッシングの実装を見つけました。勉強し続ける。
https://github.com/GITHUB243884919/ChangeEQForUnity
この実装を確認すると、効果はおおよそ次のようになります。
画像
そのコアコードは次のとおりです。

/// /// Combine SkinnedMeshRenderers together and share one skeleton. /// Merge materials will reduce the drawcalls, but it will increase the size of memory. /// /// The skeleton is a prefab with only transfrom, it is very vivid, just a skeleton. /// Meshes are SkinnedMeshRenderer components on each body part. /// Because it will be merged eventually, there is no need to parent the bones of each component into a skeleton. /// However, the weapon is different, the weapon does not participate in the merger, so it is still necessary to set the parent node. /// /// combine meshes to this skeleton(a gameobject) /// meshes need to be merged /// merge materials or not public void CombineObject (GameObject skeleton, SkinnedMeshRenderer[] meshes, bool combine = false) { // Fetch all bones of the skeleton // transforms is a list of all transform components on the skeleton List transforms = new List() transforms.AddRange(skeleton.GetComponentsInChildren(true)) // the list of materials // materials is a list of all materials on all body parts List materials = new List() // the list of meshes // combineInstances is a list of all meshes on all body parts List combineInstances = new List() //the list of bones List bones = new List() // Below informations only are used for merge materilas(bool combine = true) List oldUV = null Material newMaterial = null Texture2D newDiffuseTex = null // Collect information from meshes // Save all Material, Mesh, Transform (bones) to the corresponding List for (int i = 0 i // Collect materials materials.AddRange(smr.materials) // Collect meshes for (int sub = 0 sub new CombineInstance() ci.mesh = smr.sharedMesh ci.subMeshIndex = sub combineInstances.Add(ci) } // Collect bones // Collecting bones is a bit different: only collect what is in the skeleton. This should involve specific art standards. for (int j = 0 j int tBase = 0 for (tBase = 0 tBase if (smr.bones[j].name.Equals(transforms[tBase].name)) { //Debug.Log('Equals bones ' + smr.bones[j].name) bones.Add(transforms[tBase]) break } } } } // merge materials // Material merge, mainly to deal with texture and its UV if (combine) { newMaterial = new Material (Shader.Find ('Mobile/Diffuse')) oldUV = new List() // merge the texture // Combine textures (taken from the collected materials) // Textures is a list of all textures List Textures = new List() for (int i = 0 i as Texture2D) } //All textures are merged into newDiffuseTex this big texture newDiffuseTex = new Texture2D(COMBINE_TEXTURE_MAX, COMBINE_TEXTURE_MAX, TextureFormat.RGBA32, true) Rect[] uvs = newDiffuseTex.PackTextures(Textures.ToArray(), 0) newMaterial.mainTexture = newDiffuseTex // reset uv // Calculate the merged uv based on the original single uv, uva is single, and uvb is merged. // uva is taken from combineInstances[j].mesh.uv // Save uva with oldUV. Why save uva? Isn't it single? Skip and look down // Calculate uvb and assign it to combineInstances[j].mesh.uv Vector2[] uva, uvb for (int j = 0 j //uva = (Vector2[])(combineInstances[j].mesh.uv) uva = combineInstances[j].mesh.uv uvb = new Vector2[uva.Length] for (int k = 0 k new Vector2((uva[k].x * uvs[j].width) + uvs[j].x, (uva[k].y * uvs[j].height) + uvs[j].y) } //oldUV.Add(combineInstances[j].mesh.uv) oldUV.Add(uva) combineInstances[j].mesh.uv = uvb } } // Create a new SkinnedMeshRenderer SkinnedMeshRenderer oldSKinned = skeleton.GetComponent () if (oldSKinned != null) { GameObject.DestroyImmediate (oldSKinned) } SkinnedMeshRenderer r = skeleton.AddComponent() r.sharedMesh = new Mesh() // Combine meshes r.sharedMesh.CombineMeshes(combineInstances.ToArray(), combine, false) // Use new bones r.bones = bones.ToArray() if (combine) { Debug.Log('combine ' + combine) r.material = newMaterial for (int i = 0 i // Why use oldUV? Isn't this a saved uva? Is it a single uv? // The reason is that this line of code does not actually affect the display, it affects the display of the uv before the Mesh merge. // The meaning of this line is to find the correct single uv in the new merge process when you want to change parts after merging. // It is also the meaning of oldUV. combineInstances[i].mesh.uv = oldUV[i] } } else { Debug.Log('combine ' + combine) r.materials = materials.ToArray() } }

これには、ボーンのマージが含まれます。パラメータがSkinnedMeshRendererであり、以前のMeshRendererではないことに注意してください。どのような違いがありますか?勉強し続ける。
私は良い記事を見つけました: https://blog.csdn.net/n5/article/details/3105872 (最終的にオリジナルを見つけるのに少し手間がかかりました。なぜそんなに多くの人が抽出したいのに、不完全なコピーなのですか?)
ここでは、スケルトンスキニングアニメーションの理由と原理を説明するアニメーションから始めます。この機能のコアテクノロジーは スキンメッシュ 、そして CombineMeshes それは、その実現に必要なステップにすぎません。
私は偉大なる神の記事を数回読みましたが、おそらくそれを理解しています。ボーンスキンアニメーションはマルチメッシュジョイントアニメーションとは異なるため、その頂点情報はボーンとスキンの情報データの影響を受けます。アニメーションデータがボーンを制御し、それに応じてメッシュが変化します。ボーンのセットは1つしかないため、メッシュをマージする必要があります。
最後に、別の質問があります。マテリアルを1つにマージする必要がありますか?