-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
PiMaker
committed
Jul 11, 2021
1 parent
7ad04ae
commit 5a12b06
Showing
16 changed files
with
547 additions
and
0 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,162 @@ | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using UnityEditor; | ||
using UnityEngine; | ||
using VRC.Udon; | ||
using UdonSharp; | ||
|
||
#if UNITY_EDITOR | ||
|
||
public class ALBlendGenerator : MonoBehaviour | ||
{ | ||
[Header("Internal Stuff")] | ||
public Material AudioLinkBlendMaterial; | ||
public UdonSharpProgramAsset ALConfigure; | ||
|
||
[Header("User Configuration")] | ||
[Tooltip("Which AudioLink Band to react to (0=bass, 1=mid_low, 2=mid_high, 3=treble) - this is encoded into the name of the created GameObject")] | ||
[Range(0, 3)] | ||
public int AudioLinkBand = 0; | ||
|
||
[HideInInspector] | ||
public float min = 0.0f, max = 1.0f; | ||
[HideInInspector] | ||
public int shape = 0; | ||
|
||
public void DoWork() | ||
{ | ||
var mesh = this.GetComponent<SkinnedMeshRenderer>(); | ||
|
||
var initialVal = mesh.GetBlendShapeWeight(shape); | ||
|
||
var newMesh = new Mesh(); | ||
|
||
var scale = this.transform.localScale; | ||
this.transform.localScale = Vector3.one; | ||
|
||
mesh.SetBlendShapeWeight(shape, max); | ||
mesh.BakeMesh(newMesh); | ||
|
||
var bounds1 = CalculateBounds(newMesh); | ||
|
||
var vertexPositions = new List<Vector3>(newMesh.vertices); | ||
var normalPositions = new List<Vector3>(newMesh.normals); | ||
var uvPositions = new List<Vector2>(newMesh.uv); | ||
|
||
mesh.SetBlendShapeWeight(shape, min); | ||
mesh.BakeMesh(newMesh); | ||
|
||
var bounds2 = CalculateBounds(newMesh); | ||
|
||
this.transform.localScale = scale; | ||
|
||
newMesh.SetUVs(1, vertexPositions); | ||
newMesh.SetUVs(2, normalPositions); | ||
newMesh.SetUVs(3, uvPositions); | ||
|
||
var meshName = this.gameObject.transform.GetHierarchyPath().Replace("\\", "_").Replace("/", "_"); | ||
SaveMesh(newMesh, meshName); | ||
|
||
mesh.SetBlendShapeWeight(shape, initialVal); | ||
|
||
// disable parent renderer, children will render instead | ||
mesh.enabled = false; | ||
|
||
foreach (var existingChild in this.transform) | ||
{ | ||
var subFilter = (existingChild as Transform)?.GetComponent<MeshFilter>(); | ||
if (subFilter != null) | ||
{ | ||
subFilter.sharedMesh = newMesh; | ||
} | ||
} | ||
|
||
var newObj = new GameObject(this.gameObject.name + "_AL;" + this.AudioLinkBand, | ||
typeof(MeshRenderer), typeof(MeshFilter), typeof(UdonBehaviour)); | ||
|
||
newObj.transform.SetParent(this.gameObject.transform); | ||
newObj.transform.localPosition = Vector3.zero; | ||
newObj.transform.localRotation = Quaternion.identity; | ||
newObj.transform.localScale = Vector3.one; | ||
|
||
var filter = newObj.GetComponent<MeshFilter>(); | ||
filter.sharedMesh = newMesh; | ||
filter.sharedMesh.bounds = new Bounds(Vector3.zero, new Vector3( | ||
Mathf.Max(Mathf.Abs(bounds1.extents.x), Mathf.Abs(bounds2.extents.x)) * 0.5f, | ||
Mathf.Max(Mathf.Abs(bounds1.extents.y), Mathf.Abs(bounds2.extents.y)) * 0.5f, | ||
Mathf.Max(Mathf.Abs(bounds1.extents.z), Mathf.Abs(bounds2.extents.z)) * 0.5f | ||
)); | ||
|
||
var rend = newObj.GetComponent<MeshRenderer>(); | ||
this.AudioLinkBlendMaterial.enableInstancing = true; | ||
rend.sharedMaterials = Enumerable.Repeat(this.AudioLinkBlendMaterial, mesh.sharedMaterials.Length).ToArray(); | ||
|
||
var udon = newObj.GetComponent<UdonBehaviour>(); | ||
udon.programSource = ALConfigure; | ||
} | ||
|
||
void SaveMesh(Mesh mesh, string name) | ||
{ | ||
var path = "Assets\\_pi_\\_AudioLinkBlend\\generated\\"; | ||
System.IO.Directory.CreateDirectory(path); | ||
path += name + ".asset"; | ||
MeshUtility.Optimize(mesh); | ||
AssetDatabase.CreateAsset(mesh, path); | ||
AssetDatabase.SaveAssets(); | ||
} | ||
|
||
Bounds CalculateBounds(Mesh mesh) | ||
{ | ||
var min = Vector3.one * float.MaxValue; | ||
var max = Vector3.one * float.MinValue; | ||
foreach (var v in mesh.vertices) | ||
{ | ||
// please don't ask me why we need to multiply by 500 here... | ||
min = Vector3.Min(v * 500.0f, min); | ||
max = Vector3.Max(v * 500.0f, max); | ||
} | ||
var ret = new Bounds(Vector3.zero, new Vector3( | ||
Mathf.Max(Mathf.Abs(min.x), Mathf.Abs(max.x)) * 0.5f, | ||
Mathf.Max(Mathf.Abs(min.y), Mathf.Abs(max.y)) * 0.5f, | ||
Mathf.Max(Mathf.Abs(min.z), Mathf.Abs(max.z)) * 0.5f | ||
)); | ||
return ret; | ||
} | ||
|
||
public List<string> GetBlendShapes() | ||
{ | ||
var mesh = this.GetComponent<SkinnedMeshRenderer>().sharedMesh; | ||
var ret = new List<string>(); | ||
for (int i = 0; i < mesh.blendShapeCount; i++) | ||
{ | ||
ret.Add(mesh.GetBlendShapeName(i)); | ||
} | ||
return ret; | ||
} | ||
} | ||
|
||
[CustomEditor(typeof(ALBlendGenerator))] | ||
public class ALBlendGeneratorEditor : Editor | ||
{ | ||
public override void OnInspectorGUI() | ||
{ | ||
DrawDefaultInspector(); | ||
|
||
ALBlendGenerator gen = (ALBlendGenerator)target; | ||
|
||
EditorGUILayout.LabelField("Blend Shape:"); | ||
var shapes = gen.GetBlendShapes(); | ||
gen.shape = EditorGUILayout.Popup(gen.shape, shapes.ToArray()); | ||
|
||
EditorGUILayout.LabelField("Blend Range:"); | ||
EditorGUILayout.MinMaxSlider(ref gen.min, ref gen.max, 0.0f, 1.0f); | ||
|
||
if (GUILayout.Button("Generate")) | ||
{ | ||
gen.DoWork(); | ||
} | ||
} | ||
|
||
} | ||
|
||
#endif |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
%YAML 1.1 | ||
%TAG !u! tag:unity3d.com,2011: | ||
--- !u!114 &11400000 | ||
MonoBehaviour: | ||
m_ObjectHideFlags: 0 | ||
m_CorrespondingSourceObject: {fileID: 0} | ||
m_PrefabInstance: {fileID: 0} | ||
m_PrefabAsset: {fileID: 0} | ||
m_GameObject: {fileID: 0} | ||
m_Enabled: 1 | ||
m_EditorHideFlags: 0 | ||
m_Script: {fileID: 11500000, guid: c333ccfdd0cbdbc4ca30cef2dd6e6b9b, type: 3} | ||
m_Name: ALConfigure | ||
m_EditorClassIdentifier: | ||
serializedUdonProgramAsset: {fileID: 11400000, guid: 6381663f2156a724790b248df4b9b562, | ||
type: 2} | ||
udonAssembly: | ||
assemblyError: | ||
sourceCsScript: {fileID: 11500000, guid: b05a9d5f502351a458ad740db5938ddd, type: 3} | ||
behaviourSyncMode: 0 | ||
behaviourIDHeapVarName: __refl_const_intnl_udonTypeID | ||
compileErrors: [] | ||
hasInteractEvent: 0 | ||
serializationData: | ||
SerializedFormat: 2 | ||
SerializedBytes: | ||
ReferencedUnityObjects: [] | ||
SerializedBytesString: | ||
Prefab: {fileID: 0} | ||
PrefabModificationsReferencedUnityObjects: [] | ||
PrefabModifications: [] | ||
SerializationNodes: | ||
- Name: fieldDefinitions | ||
Entry: 7 | ||
Data: 0|System.Collections.Generic.Dictionary`2[[System.String, mscorlib],[UdonSharp.Compiler.FieldDefinition, | ||
UdonSharp.Editor]], mscorlib | ||
- Name: comparer | ||
Entry: 7 | ||
Data: 1|System.Collections.Generic.GenericEqualityComparer`1[[System.String, | ||
mscorlib]], mscorlib | ||
- Name: | ||
Entry: 8 | ||
Data: | ||
- Name: | ||
Entry: 12 | ||
Data: 0 | ||
- Name: | ||
Entry: 13 | ||
Data: | ||
- Name: | ||
Entry: 8 | ||
Data: |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
using UdonSharp; | ||
using UnityEngine; | ||
using VRC.SDKBase; | ||
|
||
public class ALConfigure : UdonSharpBehaviour | ||
{ | ||
void Start() | ||
{ | ||
var rend = this.GetComponent<MeshRenderer>(); | ||
|
||
var bandSplit = this.gameObject.name.Split(';'); | ||
var band = int.Parse(bandSplit[bandSplit.Length - 1]); | ||
|
||
var mpb = new MaterialPropertyBlock(); | ||
rend.GetPropertyBlock(mpb); | ||
mpb.SetInt("_ALBand", band); | ||
rend.SetPropertyBlock(mpb); | ||
|
||
// disable ourselves so we don't use any performance (hopefully) | ||
this.enabled = false; | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
Shader "_pi_/AudioLinkBlend" | ||
{ | ||
Properties | ||
{ | ||
_Color ("Color", Color) = (1,1,1,1) | ||
_MainTex ("Albedo (RGB)", 2D) = "white" {} | ||
_Glossiness ("Smoothness", Range(0,1)) = 0.5 | ||
_Metallic ("Metallic", Range(0,1)) = 0.0 | ||
|
||
_ALBand ("AudioLink Band", Int) = 0 | ||
|
||
[HideInInspector] _AudioLink ("AudioLink Texture", 2D) = "black" {} | ||
} | ||
SubShader | ||
{ | ||
Tags { "RenderType"="Opaque" "DisableBatching"="true" } | ||
LOD 100 | ||
|
||
CGPROGRAM | ||
#pragma surface surf Standard addshadow fullforwardshadows vertex:vert | ||
#pragma target 3.0 | ||
|
||
#include "../../AudioLink/Shaders/AudioLink.cginc" | ||
|
||
sampler2D _MainTex; | ||
|
||
struct Input { | ||
float2 uv_MainTex; | ||
}; | ||
|
||
half _Glossiness; | ||
half _Metallic; | ||
fixed4 _Color; | ||
|
||
UNITY_INSTANCING_BUFFER_START(Props) | ||
UNITY_DEFINE_INSTANCED_PROP(uint, _ALBand) | ||
UNITY_INSTANCING_BUFFER_END(Props) | ||
|
||
void vert(inout appdata_full v, out Input o) { | ||
UNITY_INITIALIZE_OUTPUT(Input, o); | ||
|
||
if (AudioLinkData(ALPASS_GENERALVU + uint2(0, 0)).x >= 0) { | ||
uint band = UNITY_ACCESS_INSTANCED_PROP(Props, _ALBand); | ||
float intens = AudioLinkData(ALPASS_AUDIOLINK + int2(0, band)).r * 100.0; | ||
|
||
v.vertex = lerp(v.vertex, v.texcoord1, intens); | ||
v.normal = lerp(v.normal, v.texcoord2, intens); | ||
o.uv_MainTex = v.texcoord = lerp(v.texcoord, v.texcoord3, intens); | ||
} | ||
} | ||
|
||
void surf (Input IN, inout SurfaceOutputStandard o) { | ||
fixed4 c = tex2D (_MainTex, IN.uv_MainTex) * _Color; | ||
o.Albedo = c.rgb; | ||
o.Metallic = _Metallic; | ||
o.Smoothness = _Glossiness; | ||
o.Alpha = c.a; | ||
} | ||
ENDCG | ||
} | ||
} |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
Oops, something went wrong.