Skip to content

Commit

Permalink
Update LyumaMeshTools and add documentation.
Browse files Browse the repository at this point in the history
  • Loading branch information
lyuma committed Jun 15, 2021
1 parent a92c75a commit 036364d
Show file tree
Hide file tree
Showing 6 changed files with 124 additions and 13 deletions.
7 changes: 7 additions & 0 deletions LICENSE.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 8 additions & 0 deletions LyumaShader/Editor.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

66 changes: 53 additions & 13 deletions LyumaShader/Editor/LyumaMeshTools.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,24 +26,30 @@ public static void LyumaMeshToolsAct (MenuCommand command) {}
[MenuItem ("CONTEXT/MeshFilter/Vertex position to UV2 : LMT", false, 131)]
[MenuItem ("CONTEXT/MeshRenderer/Vertex position to UV2 : LMT", false, 131)]
[MenuItem ("CONTEXT/SkinnedMeshRenderer/Vertex position to UV2 : LMT", false, 131)]
public static void RunBakeObjectPos (MenuCommand command)
public static void RunBakeWorldPos (MenuCommand command)
{
Mesh sourcePositionMesh;
Mesh sourceMesh;
SkinnedMeshRenderer smr = null;
MeshRenderer mr = null;
MeshFilter mf = null;
if (command.context is SkinnedMeshRenderer) {
smr = command.context as SkinnedMeshRenderer;
sourceMesh = smr.sharedMesh;
sourcePositionMesh = new Mesh();
smr.BakeMesh(sourcePositionMesh);
} else if (command.context is MeshRenderer) {
mr = command.context as MeshRenderer;
mf = mr.transform.GetComponent<MeshFilter> ();
sourceMesh = mf.sharedMesh;
sourcePositionMesh = sourceMesh;
} else if (command.context is MeshFilter) {
mf = command.context as MeshFilter;
sourceMesh = mf.sharedMesh;
sourcePositionMesh = sourceMesh;
} else if (command.context is Mesh) {
sourceMesh = command.context as Mesh;
sourcePositionMesh = sourceMesh;
} else {
EditorUtility.DisplayDialog ("MergeUVs", "Unknkown context type " + command.context.GetType ().FullName, "OK", "");
throw new NotSupportedException ("Unknkown context type " + command.context.GetType ().FullName);
Expand All @@ -56,6 +62,7 @@ public static void RunBakeObjectPos (MenuCommand command)
sourceMesh.GetUVs (0, srcUV);
sourceMesh.GetUVs (2, srcUV3);
sourceMesh.GetUVs (3, srcUV4);
Vector3 [] srcPosVertices = sourcePositionMesh.vertices;
Vector3 [] srcVertices = sourceMesh.vertices;
Color [] srcColors = sourceMesh.colors; // FIXME: Should use colors?
Vector3 [] srcNormals = sourceMesh.normals;
Expand All @@ -64,7 +71,7 @@ public static void RunBakeObjectPos (MenuCommand command)
BoneWeight [] srcBoneWeights = sourceMesh.boneWeights;
var newUV2 = new Vector4[size];
for (int i = 0; i < size; i++) {
newUV2 [i] = new Vector4 (srcVertices[i].x, srcVertices[i].y, srcVertices[i].z, 0);
newUV2 [i] = new Vector4 (srcPosVertices[i].x, srcPosVertices[i].y, srcPosVertices[i].z, 0);
}
newMesh.vertices = srcVertices;
if (srcNormals != null && srcNormals.Length > 0) {
Expand Down Expand Up @@ -568,6 +575,7 @@ public static void RunCombineSameMaterial (MenuCommand command)
parentName += sourceMesh.name;
Mesh newMesh = new Mesh ();
int size = sourceMesh.vertices.Length;
newMesh.indexFormat = sourceMesh.indexFormat == UnityEngine.Rendering.IndexFormat.UInt32 || size > 65535 ? UnityEngine.Rendering.IndexFormat.UInt32 : UnityEngine.Rendering.IndexFormat.UInt16;
List<Vector4> srcUV = new List<Vector4> (); // will discard zw
List<Vector4> srcUV2 = new List<Vector4> (); // will discard zw
List<Vector4> srcUV3 = new List<Vector4> ();
Expand Down Expand Up @@ -612,12 +620,36 @@ public static void RunCombineSameMaterial (MenuCommand command)
for (int i = 0; i < newMesh.subMeshCount; i++) {
List<int> curIndices = new List<int> ();
MeshTopology topo = sourceMesh.GetTopology(materialToSubmesh[finalMaterials[i]][0]);
int minidx = -1;
foreach (int thisIndex in materialToSubmesh [finalMaterials[i]]) {
if (sourceMesh.GetTopology (thisIndex) == topo) {
curIndices.AddRange (sourceMesh.GetIndices (thisIndex));
int[] newind = sourceMesh.GetIndices (thisIndex);
/*
uint offset = sourceMesh.GetBaseVertex(thisIndex);
for (int idx = 0; idx < newind.Length; idx++) {
newind[idx] += (int)offset;
if (newind[idx] < minidx || minidx == -1) {
minidx = newind[idx];
}
}
*/
curIndices.AddRange (newind);
}
}
/*
int curl = curIndices.Count;
int maxidx = 0;
for (int idx = 0; idx < curl; idx++) {
curIndices[idx] -= minidx;
if (curIndices[idx] > maxidx) {
maxidx = curIndices[idx];
}
}
newMesh.SetIndices (curIndices.ToArray<int>(), topo, i);
if (maxidx > 32767 && newMesh.indexFormat != UnityEngine.Rendering.IndexFormat.UInt32) {
GetIndices = UnityEngine.Rendering.IndexFormat.UInt32;
}
*/
newMesh.SetIndices (curIndices.ToArray<int>(), topo, i, true);
}
newMesh.bounds = sourceMesh.bounds;
if (srcBindposes != null && srcBindposes.Length > 0) {
Expand Down Expand Up @@ -796,9 +828,9 @@ public static void RunMakeSkinned (MenuCommand command)
bw.weight1 = 1.0f;
} else {
bw.boneIndex0 = 1;
bw.weight0 = 0.99999f;
bw.weight0 = 1.0f; // 0.99999f
bw.boneIndex1 = 0;
bw.weight1 = 0.00001f;
bw.weight1 = 0.00f;
}
newBoneWeights [i] = bw;
}
Expand Down Expand Up @@ -952,11 +984,6 @@ public static void RunKeyframeBlendShapes (MenuCommand command)
if (srcUV4.Count > 0) {
newMesh.SetUVs (3, srcUV4);
}
newMesh.subMeshCount = sourceMesh.subMeshCount;
for (int i = 0; i < sourceMesh.subMeshCount; i++) {
var curIndices = sourceMesh.GetIndices (i);
newMesh.SetIndices (curIndices, sourceMesh.GetTopology (i), i);
}
newMesh.bounds = sourceMesh.bounds;
if (srcBindposes != null && srcBindposes.Length > 0) {
newMesh.bindposes = sourceMesh.bindposes;
Expand Down Expand Up @@ -1021,6 +1048,11 @@ public static void RunKeyframeBlendShapes (MenuCommand command)
newMesh.AddBlendShapeFrame (blendShapeName, weight, deltaVertices, deltaNormals, deltaTangents);
}
}
newMesh.subMeshCount = sourceMesh.subMeshCount;
for (int i = 0; i < sourceMesh.subMeshCount; i++) {
var curIndices = sourceMesh.GetIndices (i);
newMesh.SetIndices (curIndices, sourceMesh.GetTopology (i), i);
}
newMesh.name = sourceMesh.name + "_blendmerge";
Mesh meshAfterUpdate = newMesh;
if (smr != null) {
Expand Down Expand Up @@ -1263,7 +1295,11 @@ public static void RunCombineSiblingMeshes (MenuCommand command)
//}
int i = 0;
foreach (Transform t in s.bones) {
if (!boneTransToIndex.ContainsKey(t)) {
if (t == null && !boneTransToIndex.ContainsKey(smr.rootBone)) {
boneTransToIndex.Add (smr.rootBone, boneTransforms.Count);
bindposes.Add (s.sharedMesh.bindposes [i]);
boneTransforms.Add (smr.rootBone);
} else if (t != null && !boneTransToIndex.ContainsKey(t)) {
boneTransToIndex.Add (t, boneTransforms.Count);
bindposes.Add (s.sharedMesh.bindposes [i]);
boneTransforms.Add (t);
Expand Down Expand Up @@ -1409,6 +1445,10 @@ public static void RunCombineSiblingMeshes (MenuCommand command)
Transform [] thisbones = renderers [subi].bones;
int[] indexMapping = new int [thisbones.Length];
for (int i = 0; i < thisbones.Length; i++) {
if (thisbones[i] == null) {
indexMapping [i] = boneTransToIndex [smr.rootBone];
continue;
}
indexMapping [i] = boneTransToIndex [thisbones [i]];
}
for (int i = 0; i < srcBoneWeights.Count; i++) {
Expand Down Expand Up @@ -1581,4 +1621,4 @@ public static void RunCombineSiblingMeshes (MenuCommand command)
}
}
}
#endif
#endif
11 changes: 11 additions & 0 deletions LyumaShader/Editor/LyumaMeshTools.cs.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

38 changes: 38 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,44 @@ This shader requires that *all* meshes have the same **Root Bone** slot set in t

Note that this includes a copy of the built-in Standard shader for metallic setup only. Specular setup is not implemented yet, but would be easy to add if requested.

# LyumaMeshTools (LMT)

The LyumaMeshTools editor script is located in LyumaShader/Editor. It contains a set of features in the gear or right click menu of Mesh Renderer and similar components. If you want to customize these, pick the closest one and edit the source code.

- "**Vertex position to UV2 : LMT**" : records original vertex position for use with shading effects that deform properly with skinned meshes (similar to using Project From View in blender, but with all 3 axes)

- "**Merge UV with UV2 : LMT**" puts UV2.xy as the .zw components of UV. Can be used similarly as vertex colors. This frees up the second UV for baked lightmaps.

- "**Assetize Meshes : LMT**" properly duplicates the mesh out of an FBX file.

- "**Add Shadow : LMT**" adds another material sharing vertices but with a face for every face in existing materials. Can be used for a stencil or with my shadow shader to make a shadow around your mesh.

- "**Combine Same Material : LMT**" is an optimization tool to combine all copies of the same material into one. You can control this process by manually putting the same material into different slots before running this script.

- "**Remove Null Mats : LMT**" removes any material in a mesh and the corresponding polygons for any unassigned (pink) material slots. NOTE: Does not remove unused vertices.

- "**Combine Mesh Siblings : LMT**" Is an optimization tool to combine all skinned mesh renderers with the same parent into one skinned mesh renderer with multiple materials. It can also be useful to guarantee meshes are rendered in order.\
\
"Combine Mesh Siblings" now also merges blendshapes from sibling meshes. This way, you can pick any mesh to be the main Body mesh and not worry about losing blendshapes.

- "**Make Skinned Parent+Child : LMT**" Builds skinned meshes out of non-skinned: See this tutorial:\
![LyumaMeshTools tutorial](https://user-images.githubusercontent.com/39946030/122019045-41e18380-cd78-11eb-8fa0-28ec72adbbe9.mp4)

- "**Keyframe Blend Shapes : LMT**" is a unique feature that edits a mesh with blendshapes named with a percent at the end like Blink_25% Blink_50% and merges them into a single blendshape at those percents. This tool can create instant blend shapes as well as any sort of custom mesh animation from a single gesture (or activation of multiple props from variable fist pressure). There is no way to my knowledge to import such blend shapes.\
\
Most of these things could be done in blender. Add Shadow is one of the more interesting tools: it is very efficient compared to duplicating vertices, duplicating meshes or even adding passes into multiple different shaders, and it allows you to make effectively a shader pass on a different queue. It's not trivial to do this in blender.\
\
Blend shape keyframing is probably by far the most interesting. The way to use it is you must import blendshapes named like this with _ or space and a percent.\
\
The following will generate a single blendshape called coolface that hits those keyframes on the way from 0 to 100. If you weight paint a prop to your main avatar mesh, this can allow for animations upon activating the prop from a gesture, without needing a whole animator setup
> - coolface 10%
> - coolface 30%
> - coolface_50%
> - coolface_100%
You may need to run multiple tools depending on how your mesh is laid out, but Combine Mesh Siblings will get you most of the way. Make sure to disable the other meshes or delete them afterwards (will require Unpack Prefab). Also, Combine Same Material will help once you have merged meshes.


# Other Contents

* LyumaShader/DropShadowLite.shader: This renders a flat drop shadow behind the object. Usually used by making a duplicate of your material or mesh and applying this shader to the duplicate. It contains its own offset, so it is ok to apply to a SkinnedMeshRenderer of an existing armature.
Expand Down
7 changes: 7 additions & 0 deletions README.md.meta

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit 036364d

Please sign in to comment.