Skip to content

Instantly share code, notes, and snippets.

@sokuhatiku
Last active July 22, 2019 19:21
Show Gist options
  • Save sokuhatiku/7dd44c7de34d3c039acb647d5db42172 to your computer and use it in GitHub Desktop.
Save sokuhatiku/7dd44c7de34d3c039acb647d5db42172 to your computer and use it in GitHub Desktop.
#if UNITY_EDITOR
using System.Collections.Generic;
using UnityEngine;
using UnityEditor;
namespace Sokuhatiku.TunnelShader
{
public class TunnelMeshCompressor : EditorWindow
{
private const string Name = "Tunnel Mesh Complesser";
[MenuItem("Window/" + Name)]
public static void Open()
{
var window = GetWindow<TunnelMeshCompressor>();
window.titleContent = new GUIContent(Name);
}
private MeshFilter filter;
private void OnGUI()
{
bool complessAction = false;
bool targetChanged = false;
EditorGUILayout.LabelField(Name, EditorStyles.largeLabel);
EditorGUILayout.Space();
EditorGUI.BeginChangeCheck();
{
filter = EditorGUILayout.ObjectField("Target", filter, typeof(MeshFilter), true) as MeshFilter;
}
targetChanged = EditorGUI.EndChangeCheck();
EditorGUILayout.Space();
EditorGUI.BeginDisabledGroup(filter == null || EditorApplication.isPlayingOrWillChangePlaymode);
{
complessAction = GUILayout.Button("Compless", GUILayout.Height(25));
}
EditorGUI.EndDisabledGroup();
if (targetChanged && filter != null)
{
Selection.SetActiveObjectWithContext(filter.gameObject, filter);
}
if (complessAction && filter != null)
{
Process(filter);
}
}
private void Process(MeshFilter filter)
{
var savePath = EditorUtility.SaveFilePanelInProject("Save complessed mesh", "Complessed", "asset", "");
if (string.IsNullOrEmpty(savePath))
{
return;
}
Undo.RecordObjects(new Object[] { filter, filter.transform }, "Tunnel Mesh Compless");
var localToWorld = filter.transform.localToWorldMatrix;
filter.transform.rotation = Quaternion.identity;
var worldToLocal = filter.transform.worldToLocalMatrix;
Mesh mesh = ComplessMesh(filter.sharedMesh, localToWorld, worldToLocal);
AssetDatabase.CreateAsset(mesh, savePath);
filter.sharedMesh = mesh;
}
private static Mesh ComplessMesh(Mesh refMesh, Matrix4x4 localToWorld, Matrix4x4 worldToLocal)
{
var bounds = new Bounds(
new Vector3(0, 2.5f, 0),
new Vector3(4, 5, 4));
int positionUvChannel = 2;
var mesh = Instantiate(refMesh);
var refVertices = refMesh.vertices;
var vertices = new Vector3[refVertices.Length];
var posUVs = new Vector3[refVertices.Length];
for (int i = 0; i < vertices.Length; i++)
{
var localVertex = localToWorld.MultiplyPoint3x4(refVertices[i]);
var clampedVertex = new Vector4(
Mathf.Clamp(localVertex.x, bounds.min.x, bounds.max.x),
Mathf.Clamp(localVertex.y, bounds.min.y, bounds.max.y),
Mathf.Clamp(localVertex.z, bounds.min.z, bounds.max.z));
vertices[i] = worldToLocal.MultiplyPoint3x4(clampedVertex);
posUVs[i] = worldToLocal.MultiplyPoint(localVertex);
}
mesh.vertices = vertices;
mesh.SetUVs(positionUvChannel, new List<Vector3>(posUVs));
mesh.bounds = bounds;
return mesh;
}
}
}
#endif
@sokuhatiku
Copy link
Author

sokuhatiku commented Jul 22, 2019

※これはTunnelShaderを使ったコンテンツをVケット3に提出するために、メッシュの頂点座標を指定範囲内に圧縮するスクリプトです。

使用前に必ずプロジェクトのバックアップを取って下さい。

こちらを右クリックしてダウンロードして下さい。

Unityプロジェクト内の適当な場所に配置してください。ただし、エディタ上でしか動かないスクリプトなので、ブースアセットには混ぜないで下さい。

使い方

正常にインストールが完了すると、以下のようにメニューに「Tunnel Mesh Complesser」という項目が出現します。
image

項目を選ぶと以下のようなUIが出ますので、画像のように圧縮を行いたいTunnelメッシュを含んだオブジェクトを選択します。
image

Complessを押すとメッシュが圧縮され、ブース範囲内に収まります。圧縮したメッシュは元のメッシュとは別の場所に保存されます。また、Tunnelオブジェクトの回転情報は圧縮済みメッシュに焼きこまれ、Transformの回転はリセットされます。メッシュの見た目が一時的に汚くなりますが、次の項で修正します。

圧縮メッシュの作成以外の処理はすべてUndo(Ctrl+z)で取り消しが可能です。
image

その後、TunnelUnlit.shader内にある2種類のvert関数を、それぞれ以下のように修正します。

v2f vert (appdata_full v)
{
	v.vertex = float4(v.texcoord2.xyz, 1); // 頂点復元処理を追加
	v2f o;
	o.vertex = UnityObjectToClipPos(v.vertex);
	o.uv = TRANSFORM_TEX(v.texcoord1, _MainTex);

	USE_SERIALIZED_MATRIX(_ClipMatrix)
	V2F_NEAR_CLIP(_ClipMatrix, v.vertex, o)
	return o;
}
v2f vert(appdata_full v) // appdata_baseからappdata_fullに変更
{
	v.vertex = float4(v.texcoord2.xyz, 1); // 頂点復元処理を追加
	v2f o;
	TRANSFER_SHADOW_CASTER_NORMALOFFSET(o)

	USE_SERIALIZED_MATRIX(_ClipMatrix)
	V2F_NEAR_CLIP(_ClipMatrix, v.vertex, o)
	return o;
}

以上の操作を行うと(何か干渉がなければ)ブースサイズ制限を突破しつつ、見た目が正常に戻ります。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment