// Use this for initialization void Start() { renderer = this.GetComponent<Renderer>(); mesh = this.GetComponent<MeshFilter>(); prevTileType = tileType; UpdateTileRepresentation(); }
private static void DoParseCollision() { if (Selection.activeGameObject == null) { return; } //get known layers string[] layers = new string[32]; for (int i = 0; i < 32; i++) { layers[i] = LayerMask.LayerToName(i); } //do work var go = Selection.activeGameObject; foreach (var child in go.GetAllChildrenAndSelf()) { var arr = StringUtil.SplitFixedLength(child.name, ".", 3); if (string.Equals(arr[0], "collision", System.StringComparison.OrdinalIgnoreCase) || string.Equals(arr[0], "trigger", System.StringComparison.OrdinalIgnoreCase)) { var bTrigger = string.Equals(arr[0], "trigger", System.StringComparison.OrdinalIgnoreCase); //remove old collider if (child.HasComponent <Collider>()) { child.RemoveComponents <Collider>(); } //set collider if (string.IsNullOrEmpty(arr[1])) { arr[1] = "box"; //default to box } else { arr[1] = arr[1].ToLower(); } MeshFilter filter = child.GetComponent <MeshFilter>(); switch (arr[1]) { case "mesh": var meshCollider = child.AddComponent <MeshCollider>(); meshCollider.isTrigger = bTrigger; if (filter != null) { meshCollider.sharedMesh = child.GetComponent <MeshFilter>().sharedMesh; } break; case "box": var boxCollider = child.AddComponent <BoxCollider>(); boxCollider.isTrigger = bTrigger; if (filter != null && filter.sharedMesh != null) { var bounds = filter.sharedMesh.bounds; boxCollider.center = bounds.center; boxCollider.size = bounds.size; } break; case "sphere": var sphereCollider = child.AddComponent <SphereCollider>(); sphereCollider.isTrigger = bTrigger; if (filter != null && filter.sharedMesh != null) { var bounds = com.spacepuppy.Geom.Sphere.FromMesh(filter.sharedMesh, spacepuppy.Geom.BoundingSphereAlgorithm.FromBounds); sphereCollider.center = bounds.Center; sphereCollider.radius = bounds.Radius; } break; case "capsule": var capCollider = child.AddComponent <CapsuleCollider>(); capCollider.isTrigger = bTrigger; if (filter != null && filter.sharedMesh != null) { var bounds = filter.sharedMesh.bounds; capCollider.center = bounds.center; capCollider.height = bounds.size.y; capCollider.radius = Mathf.Max(bounds.extents.x, bounds.extents.z); } break; } //set layer if (!string.IsNullOrEmpty(arr[2])) { for (int i = 0; i < layers.Length; i++) { if (string.Equals(arr[2], layers[i], System.StringComparison.OrdinalIgnoreCase)) { child.gameObject.layer = i; break; } } } if (child.HasComponent <Renderer>()) { child.GetComponent <Renderer>().enabled = false; } } } }
public void SetTooltip(string text) { if (Tooltip == null) { TooltipRendererA = new AllodsTextRenderer(Fonts.Font2, Font.Align.Left, 0, 0, false, 12); Tooltip = Utils.CreateObject(); Tooltip.transform.parent = transform; TooltipRenderer = Tooltip.AddComponent <MeshRenderer>(); TooltipFilter = Tooltip.AddComponent <MeshFilter>(); TooltipBall = Images.LoadImage("graphics/interface/ball.bmp", 0, Images.ImageType.AllodsBMP); Material[] materials = new Material[] { new Material(MainCamera.MainShader), new Material(MainCamera.MainShader) }; materials[0].mainTexture = TooltipBall; TooltipRenderer.materials = materials; GameObject TooltipText = TooltipRendererA.GetNewGameObject(0.01f, Tooltip.transform, 100); TooltipRendererA.Material.color = new Color32(165, 121, 49, 255); TooltipText.transform.localPosition = new Vector3(6, 6, -0.02f); } Tooltip.SetActive(true); float topX = lastMouseX; float topY = lastMouseY; text = text.Replace('#', '\n').Replace("~", ""); TooltipRendererA.Text = text; // ideal position for the tooltip is top/right of the mouse. // but if it doesn't fit, should be moved around. topX = lastMouseX; topY = lastMouseY - TooltipRendererA.Height - 12; float fw = TooltipRendererA.ActualWidth + 12; float fh = TooltipRendererA.Height + 12; if (topX + fw > Screen.width) { topX = Screen.width - fw; } if (topY + fh > Screen.height) { topY = Screen.height - fh; } if (topX < 0) { topX = 0; } if (topY < 0) { topY = 0; } Tooltip.transform.localPosition = new Vector3(topX, topY, MainCamera.MouseZ + 0.01f); TooltipBuilder.Reset(); TooltipBuilder.AddQuad(0, 0, 0, 4, 4); TooltipBuilder.AddQuad(0, TooltipRendererA.ActualWidth + 8, 0, 4, 4); TooltipBuilder.AddQuad(0, TooltipRendererA.ActualWidth + 8, TooltipRendererA.Height + 6, 4, 4); TooltipBuilder.AddQuad(0, 0, TooltipRendererA.Height + 6, 4, 4); // now render border quads float bw = TooltipRendererA.ActualWidth + 6; float bh = TooltipRendererA.Height + 6 - 2; // 2 = difference between "LineHeight" and our custom LineHeight of 12 // top border bright TooltipBuilder.CurrentMesh = 1; TooltipBuilder.CurrentColor = new Color32(165, 121, 49, 255); TooltipBuilder.CurrentPosition = new Vector3(3, 1); TooltipBuilder.NextVertex(); TooltipBuilder.CurrentColor = new Color32(165, 121, 49, 255); TooltipBuilder.CurrentPosition = new Vector3(3 + bw, 1); TooltipBuilder.NextVertex(); // top border dark TooltipBuilder.CurrentColor = new Color32(82, 60, 24, 255); TooltipBuilder.CurrentPosition = new Vector3(3 + bw, 1 + 2); TooltipBuilder.NextVertex(); TooltipBuilder.CurrentColor = new Color32(82, 60, 24, 255); TooltipBuilder.CurrentPosition = new Vector3(3, 1 + 2); TooltipBuilder.NextVertex(); // bottom border bright TooltipBuilder.CurrentMesh = 1; TooltipBuilder.CurrentColor = new Color32(165, 121, 49, 255); TooltipBuilder.CurrentPosition = new Vector3(3, 3 + bh); TooltipBuilder.NextVertex(); TooltipBuilder.CurrentColor = new Color32(165, 121, 49, 255); TooltipBuilder.CurrentPosition = new Vector3(3 + bw, 3 + bh); TooltipBuilder.NextVertex(); // bottom border dark TooltipBuilder.CurrentColor = new Color32(82, 60, 24, 255); TooltipBuilder.CurrentPosition = new Vector3(3 + bw, 3 + bh + 2); TooltipBuilder.NextVertex(); TooltipBuilder.CurrentColor = new Color32(82, 60, 24, 255); TooltipBuilder.CurrentPosition = new Vector3(3, 3 + bh + 2); TooltipBuilder.NextVertex(); // left border bright TooltipBuilder.CurrentMesh = 1; TooltipBuilder.CurrentColor = new Color32(165, 121, 49, 255); TooltipBuilder.CurrentPosition = new Vector3(1, 3); TooltipBuilder.NextVertex(); TooltipBuilder.CurrentColor = new Color32(165, 121, 49, 255); TooltipBuilder.CurrentPosition = new Vector3(1, 3 + bh); TooltipBuilder.NextVertex(); // left border dark TooltipBuilder.CurrentColor = new Color32(82, 60, 24, 255); TooltipBuilder.CurrentPosition = new Vector3(1 + 2, 3 + bh); TooltipBuilder.NextVertex(); TooltipBuilder.CurrentColor = new Color32(82, 60, 24, 255); TooltipBuilder.CurrentPosition = new Vector3(1 + 2, 3); TooltipBuilder.NextVertex(); // right border bright TooltipBuilder.CurrentMesh = 1; TooltipBuilder.CurrentColor = new Color32(165, 121, 49, 255); TooltipBuilder.CurrentPosition = new Vector3(3 + bw, 3); TooltipBuilder.NextVertex(); TooltipBuilder.CurrentColor = new Color32(165, 121, 49, 255); TooltipBuilder.CurrentPosition = new Vector3(3 + bw, 3 + bh); TooltipBuilder.NextVertex(); // right border dark TooltipBuilder.CurrentColor = new Color32(82, 60, 24, 255); TooltipBuilder.CurrentPosition = new Vector3(3 + bw + 2, 3 + bh); TooltipBuilder.NextVertex(); TooltipBuilder.CurrentColor = new Color32(82, 60, 24, 255); TooltipBuilder.CurrentPosition = new Vector3(3 + bw + 2, 3); TooltipBuilder.NextVertex(); // BACKGROUND QUAD TooltipBuilder.AddQuad(TooltipBuilder.CurrentMesh, 3, 3, bw, bh, new Color32(33, 44, 33, 255)); TooltipFilter.mesh = TooltipBuilder.ToMesh(MeshTopology.Quads, MeshTopology.Quads); }
public override void CreateMesh(string materialPath = "") { #if UNITY_EDITOR gameObject.layer = LayerMask.NameToLayer("SceneComponent"); Vector3[] vertexes = wallData.GetVertices(); Vector3 p1 = vertexes[0]; // Vector2.zero; Vector3 p2 = vertexes[1]; // wallData.GetNodeVec3(wallData.lenth); Vector3 p3 = vertexes[2]; // p2 + new Vector3(0, wallData.h, 0); Vector3 p4 = vertexes[3]; // p1 + new Vector3(0, wallData.h, 0); Texture2D texture = AssetDatabase.LoadAssetAtPath <Texture2D>("Assets/Materials/Shaders/tang/Wall.jpg"); MeshFilter meshFilter = gameObject.AddComponentUnique <MeshFilter>(true); MeshRenderer meshRenderer = gameObject.AddComponentUnique <MeshRenderer>(true); MeshCollider meshCollider = gameObject.AddComponentUnique <MeshCollider>(true); // 初始化mesh uv 等add by TangJian 2017/12/20 17:04:45 { // Shader shader = Shader.Find("Custom/Unlit/Transparent"); Shader shader = Shader.Find("Tang/Unlit/PureColor"); { Mesh mesh = AssetDatabase.LoadAssetAtPath <Mesh>(materialPath + ".asset"); if (mesh == null) { mesh = new Mesh(); AssetDatabase.CreateAsset(mesh, materialPath + ".asset"); mesh = AssetDatabase.LoadAssetAtPath <Mesh>(materialPath + ".asset"); } // 为网格创建顶点数组 Vector3[] vertices = new Vector3[4] { p1, p2, p3, p4 }; mesh.vertices = vertices; // 通过顶点为网格创建三角形 int[] triangles = new int[2 * 3] { 0, 1, 2, 0, 2, 3 }; mesh.triangles = triangles; mesh.uv = new Vector2[] { new Vector2(0, 0), new Vector2(0, 1), new Vector2(1, 1), new Vector2(1, 0) }; meshCollider.sharedMesh = mesh; meshFilter.sharedMesh = mesh; } Material material = AssetDatabase.LoadAssetAtPath <Material>(materialPath + ".mat"); if (material == null) { material = new Material(shader); AssetDatabase.CreateAsset(material, materialPath + ".mat"); material = AssetDatabase.LoadAssetAtPath <Material>(materialPath + ".mat"); } else { material.shader = shader; } material.mainTexture = texture; material.renderQueue = 2000; material.SetColor("MulColor", new Color(59f / 255f, 32f / 255f, 12f / 255f, 1f)); meshRenderer.sharedMaterial = material; meshRenderer.enabled = false; //AssetDatabase.SaveAssets(); } // 创建Renderer add by TangJian 2018/10/15 16:34 { GameObject rendererGameObject = gameObject.GetChild("Renderer", true); // rendererGameObject.DestoryChildren(); GameObject renderer1GameObject = rendererGameObject.GetChild("Renderer1", true); renderer1GameObject.layer = LayerMask.NameToLayer("Default"); MeshFilter rendererMeshFilter = renderer1GameObject.AddComponentUnique <MeshFilter>(true); MeshRenderer rendererMeshRenderer = renderer1GameObject.AddComponentUnique <MeshRenderer>(true); MeshCollider rendererMeshCollider = renderer1GameObject.AddComponentUnique <MeshCollider>(true); // 设置Renderer网格 add by TangJian 2018/10/15 16:34 rendererMeshCollider.sharedMesh = meshCollider.sharedMesh; rendererMeshFilter.sharedMesh = meshFilter.sharedMesh; // 设置Renderer材质 add by TangJian 2018/10/15 16:34 rendererMeshRenderer.sharedMaterial = meshRenderer.sharedMaterial; // 添加阴影 add by TangJian 2018/10/15 16:36 // renderer1GameObject.AddComponentUnique<ShadowReceiver>(); } #endif }
public bool DisableInvisibleRenderers() { // 确保产生玩家 if (playerContext == null || playerContext.flagSelfEntity == null) { Debug.LogErrorFormat("MinRendererSetSampler.DisableInvisibleRenderers error, playerContext.flagSelfEntity is null"); return(false); } // 确保地形加载完毕 if (!SingletonManager.Get <DynamicScenesController>().IsAllVisibleTerrianLoaded(playerContext.flagSelfEntity.position.Value)) { Debug.LogErrorFormat("MinRendererSetSampler.DisableInvisibleRenderers error, terrains were not loaded fully"); return(false); } // 首先恢复上次禁用的渲染体 RecoveryLastCollects(); Debug.LogFormat("DisableInvisibleRenderers call, Recovery last collects, time:{0}", System.DateTime.Now); // 遍历所有MeshRenderer集合 MeshRenderer[] mrs = FindObjectsOfType <MeshRenderer>(); Debug.LogFormat("DisableInvisibleRenderers call, find all meshrenderer count:{0} time:{1}", mrs.Length, System.DateTime.Now); // 查找所有潜在可视集合 List <MeshRenderer> visibleSet = new List <MeshRenderer>(); for (int i = 0; i < mrs.Length; i++) { MeshRenderer mr = mrs[i]; if (mr == null || !mr.gameObject.activeSelf || !mr.enabled || mr.sharedMaterials.Length <= 0) { continue; } MeshFilter mf = mr.GetComponent <MeshFilter>(); if (mf == null || mf.sharedMesh == null) { continue; } if (mr.isVisible) { visibleSet.Add(mr); } } Debug.LogFormat("DisableInvisibleRenderers call, find potential meshrenderer count:{0} time:{1}", visibleSet.Count, System.DateTime.Now); // 替换为纯色shader Dictionary <MeshRenderer, Material[]> oldRenderMats = new Dictionary <MeshRenderer, Material[]>(); Dictionary <string, MeshRenderer> renderColors = new Dictionary <string, MeshRenderer>(); //System.Text.StringBuilder sb = new System.Text.StringBuilder(); for (int i = 0; i < visibleSet.Count; i++) { MeshRenderer mr = visibleSet[i]; if (mr == null || mr.sharedMaterials.Length <= 0) { continue; } oldRenderMats.Add(mr, mr.sharedMaterials); Material mat = new Material(shader); Color32 color = colorSet[i]; mat.SetColor("_Color", color); Material[] mats = new Material[mr.sharedMaterials.Length]; for (int k = 0; k < mats.Length; k++) { mats[k] = mat; } //foreach(var mat in mats) mr.sharedMaterials = mats; string key = string.Format("{0}_{1}_{2}", color.r, color.g, color.b); renderColors.Add(key, mr); //sb.AppendLine(color.ToString()); } Debug.LogFormat("DisableInvisibleRenderers call, replace color shader, count:{0} time:{1}", oldRenderMats.Count, System.DateTime.Now); //System.IO.File.WriteAllText(@"C:\Users\Myself\Desktop\writePixels.txt", sb.ToString()); // 关闭相机的可能的后效组件影响 Dictionary <Component, bool> coms = new Dictionary <Component, bool>(); var cs = cam.GetComponents <Component>(); foreach (Component c in cs) { if (c != null) { Transform tr = c as Transform; Camera ca = c as Camera; Behaviour beh = c as Behaviour; if (tr == null && ca == null && beh != null) { coms.Add(c, beh.enabled); beh.enabled = false; } } } // 屏幕纹理捕捉 Texture2D texture = CaputureScreenTexture(); Debug.LogFormat("DisableInvisibleRenderers call, caputure screen texture, width:{0} height:{1} time:{2}", texture.width, texture.height, System.DateTime.Now); //{ // byte[] bs = texture.EncodeToPNG(); // System.IO.File.WriteAllBytes(@"C:\Users\Myself\Desktop\pixels.png", bs); //} // 恢复相机上可能的后效组件 foreach (var pair in coms) { Behaviour beh = pair.Key as Behaviour; if (beh != null) { beh.enabled = pair.Value; } } // 获取实际渲染的物体 Color32[] pixels = texture.GetPixels32(0); Debug.LogFormat("pixelsCount:{0} width:{1} height:{2} w*h:{3}", pixels.Length, texture.width, texture.height, texture.width * texture.height); HashSet <MeshRenderer> foundRenderers = new HashSet <MeshRenderer>(); int step = 1, notFoundKeysCount = 0; //sb.Length = 0; for (int i = 0; i < texture.height; i += step) { for (int j = 0; j < texture.width; j += step) { Color32 color = pixels[i * texture.width + j]; //sb.AppendLine(color.ToString()); string key = string.Format("{0}_{1}_{2}", color.r, color.g, color.b); MeshRenderer mr = null; if (!renderColors.TryGetValue(key, out mr)) { notFoundKeysCount++; continue; } if (mr != null && !foundRenderers.Contains(mr)) { foundRenderers.Add(mr); } } } Debug.LogFormat("DisableInvisibleRenderers call, get real renderers, foundcount:{0} notfoundCount:{1} time:{2}", foundRenderers.Count, notFoundKeysCount, System.DateTime.Now); //System.IO.File.WriteAllText(@"C:\Users\Myself\Desktop\readPixels.txt", sb.ToString()); // 材质复原 for (int i = 0; i < visibleSet.Count; i++) { MeshRenderer mr = visibleSet[i]; if (mr == null || mr.sharedMaterials.Length <= 0) { continue; } Material[] mats; if (oldRenderMats.TryGetValue(mr, out mats)) { mr.sharedMaterials = mats; } } Debug.LogFormat("DisableInvisibleRenderers call, recovery materials, time:{0}", System.DateTime.Now); // Disable掉实际不可见的物体 for (int i = 0; i < visibleSet.Count; i++) { MeshRenderer mr = visibleSet[i]; if (mr == null || mr.sharedMaterials.Length <= 0) { continue; } if (!foundRenderers.Contains(mr)) { mr.enabled = false; lastCollects.Add(mr); } } Debug.LogFormat("DisableInvisibleRenderers call, disable all not real renderers, time:{0}", System.DateTime.Now); if (texture != null) { DestroyImmediate(texture); } return(true); }
void ClipMesh() { MeshFilter mf = this.gameObject.GetComponent <MeshFilter>(); //顶点数组转顶点容器 List <Vector3> verticeList = new List <Vector3>(); int verticeCount = mf.mesh.vertices.Length; for (int verticeIndex = 0; verticeIndex < verticeCount; ++verticeIndex) { verticeList.Add(mf.mesh.vertices[verticeIndex]); } //三角形数组转三角形容器 List <int> triangleList = new List <int>(); int triangleCount = mf.mesh.triangles.Length; for (int triangleIndex = 0; triangleIndex < triangleCount; ++triangleIndex) { triangleList.Add(mf.mesh.triangles[triangleIndex]); } //uv坐标数组转uv坐标容器 List <Vector2> uvList = new List <Vector2>(); int uvCount = mf.mesh.uv.Length; for (int uvIndex = 0; uvIndex < uvCount; ++uvIndex) { uvList.Add(mf.mesh.uv[uvIndex]); } //顶点颜色数组转顶点颜色容器 List <Vector3> normalList = new List <Vector3>(); int normalCount = mf.mesh.normals.Length; for (int normalIndex = 0; normalIndex < normalCount; ++normalIndex) { normalList.Add(mf.mesh.normals[normalIndex]); } //Debug.Log("顶点数" + verticeList.Count); //Debug.Log("顶点索引数" + triangleList.Count); //检查每个三角面,是否存在两个顶点连接正好在直线上 for (int triangleIndex = 0; triangleIndex < triangleList.Count;) { //Debug.Log("次数记录"); int trianglePointIndex0 = triangleList[triangleIndex]; int trianglePointIndex1 = triangleList[triangleIndex + 1]; int trianglePointIndex2 = triangleList[triangleIndex + 2]; Vector3 trianglePointCoord0 = verticeList[trianglePointIndex0]; Vector3 trianglePointCoord1 = verticeList[trianglePointIndex1]; Vector3 trianglePointCoord2 = verticeList[trianglePointIndex2]; //0-1,1-2相连线段被切割 if (GetPointToClipPlaneDis(trianglePointCoord0) * GetPointToClipPlaneDis(trianglePointCoord1) < 0 && GetPointToClipPlaneDis(trianglePointCoord1) * GetPointToClipPlaneDis(trianglePointCoord2) < 0) { //求得0-1与切平面的交点 Vector3 newVertice01 = GetLinePlaneCrossPoint(trianglePointCoord0, trianglePointCoord1); int index01 = IsContainsVertice(verticeList, newVertice01); if (index01 == -1 || !m_IsClearSamePoint) { verticeList.Add(newVertice01); index01 = verticeList.Count - 1; float k01 = 0; if (!IsEqual(newVertice01.x, trianglePointCoord0.x) && !IsEqual(trianglePointCoord1.x, trianglePointCoord0.x)) { k01 = (newVertice01.x - trianglePointCoord0.x) / (trianglePointCoord1.x - trianglePointCoord0.x); } else if (!IsEqual(newVertice01.y, trianglePointCoord0.y) && !IsEqual(trianglePointCoord1.y, trianglePointCoord0.y)) { k01 = (newVertice01.y - trianglePointCoord0.y) / (trianglePointCoord1.y - trianglePointCoord0.y); } else { k01 = (newVertice01.z - trianglePointCoord0.z) / (trianglePointCoord1.z - trianglePointCoord0.z); } if (uvList.Count > 0) { Vector2 uv0 = uvList[trianglePointIndex0]; Vector2 uv1 = uvList[trianglePointIndex1]; float newUV_x = (uv1.x - uv0.x) * k01 + uv0.x; float newUV_y = (uv1.y - uv0.y) * k01 + uv0.y; uvList.Add(new Vector2(newUV_x, newUV_y)); //Debug.Log("纹理坐标" + uvList[uvList.Count - 1]); } //法向量 Vector3 normalX0 = normalList[trianglePointIndex0]; Vector3 normalX1 = normalList[trianglePointIndex1]; float newNoramlX01 = (normalX1.x - normalX0.x) * k01 + normalX0.x; float newNoramlY01 = (normalX1.y - normalX0.y) * k01 + normalX0.y; float newNoramlZ01 = (normalX1.z - normalX0.z) * k01 + normalX0.z; normalList.Add(new Vector3(newNoramlX01, newNoramlY01, newNoramlZ01)); } //求得1-2与切平面的交点 Vector3 newVertice12 = GetLinePlaneCrossPoint(trianglePointCoord1, trianglePointCoord2); int index12 = IsContainsVertice(verticeList, newVertice12); if (index12 == -1 || !m_IsClearSamePoint) { verticeList.Add(newVertice12); index12 = verticeList.Count - 1; float k12 = 0; if (!IsEqual(newVertice12.x, trianglePointCoord1.x) && !IsEqual(trianglePointCoord2.x, trianglePointCoord1.x)) { k12 = (newVertice12.x - trianglePointCoord1.x) / (trianglePointCoord2.x - trianglePointCoord1.x); } else if (!IsEqual(newVertice12.y, trianglePointCoord1.y) && !IsEqual(trianglePointCoord2.y, trianglePointCoord1.y)) { k12 = (newVertice12.y - trianglePointCoord1.y) / (trianglePointCoord2.y - trianglePointCoord1.y); } else { k12 = (newVertice12.z - trianglePointCoord1.z) / (trianglePointCoord2.z - trianglePointCoord1.z); } if (uvList.Count > 0) { Vector2 uv1 = uvList[trianglePointIndex1]; Vector2 uv2 = uvList[trianglePointIndex2]; float newUV_x = (uv2.x - uv1.x) * k12 + uv1.x; float newUV_y = (uv2.y - uv1.y) * k12 + uv1.y; uvList.Add(new Vector2(newUV_x, newUV_y)); //Debug.Log("纹理坐标" + uvList[uvList.Count - 1]); } //法向量 Vector3 normalX1 = normalList[trianglePointIndex1]; Vector3 normalX2 = normalList[trianglePointIndex2]; float newNoramlX12 = (normalX2.x - normalX1.x) * k12 + normalX1.x; float newNoramlY12 = (normalX2.y - normalX1.y) * k12 + normalX1.y; float newNoramlZ12 = (normalX2.z - normalX1.z) * k12 + normalX1.z; normalList.Add(new Vector3(newNoramlX12, newNoramlY12, newNoramlZ12)); } //插入顶点索引,以此构建新三角形 triangleList.Insert(triangleIndex + 1, index01); triangleList.Insert(triangleIndex + 2, index12); triangleList.Insert(triangleIndex + 3, index12); triangleList.Insert(triangleIndex + 4, index01); triangleList.Insert(triangleIndex + 6, trianglePointIndex0); triangleList.Insert(triangleIndex + 7, index12); triangleIndex += 9; } //1-2,2-0相连线段被切割 else if (GetPointToClipPlaneDis(trianglePointCoord1) * GetPointToClipPlaneDis(trianglePointCoord2) < 0 && GetPointToClipPlaneDis(trianglePointCoord2) * GetPointToClipPlaneDis(trianglePointCoord0) < 0) { //求得1-2与切平面的交点 Vector3 newVertice12 = GetLinePlaneCrossPoint(trianglePointCoord1, trianglePointCoord2); int index12 = IsContainsVertice(verticeList, newVertice12); if (index12 == -1 || !m_IsClearSamePoint) { verticeList.Add(newVertice12); index12 = verticeList.Count - 1; float k12 = 0; if (!IsEqual(newVertice12.x, trianglePointCoord1.x) && !IsEqual(trianglePointCoord2.x, trianglePointCoord1.x)) { k12 = (newVertice12.x - trianglePointCoord1.x) / (trianglePointCoord2.x - trianglePointCoord1.x); } else if (!IsEqual(newVertice12.y, trianglePointCoord1.y) && !IsEqual(trianglePointCoord2.y, trianglePointCoord1.y)) { k12 = (newVertice12.y - trianglePointCoord1.y) / (trianglePointCoord2.y - trianglePointCoord1.y); } else { k12 = (newVertice12.z - trianglePointCoord1.z) / (trianglePointCoord2.z - trianglePointCoord1.z); } if (uvList.Count > 0) { Vector2 uv1 = uvList[trianglePointIndex1]; Vector2 uv2 = uvList[trianglePointIndex2]; float newUV_x = (uv2.x - uv1.x) * k12 + uv1.x; float newUV_y = (uv2.y - uv1.y) * k12 + uv1.y; uvList.Add(new Vector2(newUV_x, newUV_y)); //Debug.Log("纹理坐标" + uvList[uvList.Count - 1]); } //法向量 Vector3 normalX1 = normalList[trianglePointIndex1]; Vector3 normalX2 = normalList[trianglePointIndex2]; float newNoramlX12 = (normalX2.x - normalX1.x) * k12 + normalX1.x; float newNoramlY12 = (normalX2.y - normalX1.y) * k12 + normalX1.y; float newNoramlZ12 = (normalX2.z - normalX1.z) * k12 + normalX1.z; normalList.Add(new Vector3(newNoramlX12, newNoramlY12, newNoramlZ12)); } //求得0-2与切平面的交点 Vector3 newVertice02 = GetLinePlaneCrossPoint(trianglePointCoord0, trianglePointCoord2); int index02 = IsContainsVertice(verticeList, newVertice02); if (index02 == -1 || !m_IsClearSamePoint) { verticeList.Add(newVertice02); index02 = verticeList.Count - 1; float k02 = 0; if (!IsEqual(newVertice02.x, trianglePointCoord0.x) && !IsEqual(trianglePointCoord2.x, trianglePointCoord0.x)) { k02 = (newVertice02.x - trianglePointCoord0.x) / (trianglePointCoord2.x - trianglePointCoord0.x); } else if (!IsEqual(newVertice02.y, trianglePointCoord0.y) && !IsEqual(trianglePointCoord2.y, trianglePointCoord0.y)) { k02 = (newVertice02.y - trianglePointCoord0.y) / (trianglePointCoord2.y - trianglePointCoord0.y); } else { k02 = (newVertice02.z - trianglePointCoord0.z) / (trianglePointCoord2.z - trianglePointCoord0.z); } if (uvList.Count > 0) { Vector2 uv0 = uvList[trianglePointIndex0]; Vector2 uv2 = uvList[trianglePointIndex2]; float newUV_x = (uv2.x - uv0.x) * k02 + uv0.x; float newUV_y = (uv2.y - uv0.y) * k02 + uv0.y; uvList.Add(new Vector2(newUV_x, newUV_y)); //Debug.Log("纹理坐标" + uvList[uvList.Count - 1]); } //法向量 Vector3 normalX0 = normalList[trianglePointIndex0]; Vector3 normalX2 = normalList[trianglePointIndex2]; float newNoramlX02 = (normalX2.x - normalX0.x) * k02 + normalX0.x; float newNoramlY02 = (normalX2.y - normalX0.y) * k02 + normalX0.y; float newNoramlZ02 = (normalX2.z - normalX0.z) * k02 + normalX0.z; normalList.Add(new Vector3(newNoramlX02, newNoramlY02, newNoramlZ02)); } //插入顶点索引,以此构建新三角形 //{0} //{1} triangleList.Insert(triangleIndex + 2, index12); triangleList.Insert(triangleIndex + 3, index02); triangleList.Insert(triangleIndex + 4, index12); //{2} triangleList.Insert(triangleIndex + 6, index02); triangleList.Insert(triangleIndex + 7, trianglePointIndex0); triangleList.Insert(triangleIndex + 8, index12); triangleIndex += 9; } //0-1,2-0相连线段被切割 else if (GetPointToClipPlaneDis(trianglePointCoord0) * GetPointToClipPlaneDis(trianglePointCoord1) < 0 && GetPointToClipPlaneDis(trianglePointCoord2) * GetPointToClipPlaneDis(trianglePointCoord0) < 0) { //求得0-1与切平面的交点 Vector3 newVertice01 = GetLinePlaneCrossPoint(trianglePointCoord0, trianglePointCoord1); int index01 = IsContainsVertice(verticeList, newVertice01); if (index01 == -1 || !m_IsClearSamePoint) { verticeList.Add(newVertice01); index01 = verticeList.Count - 1; float k01 = 0; if (!IsEqual(newVertice01.x, trianglePointCoord0.x) && !IsEqual(trianglePointCoord1.x, trianglePointCoord0.x)) { k01 = (newVertice01.x - trianglePointCoord0.x) / (trianglePointCoord1.x - trianglePointCoord0.x); } else if (!IsEqual(newVertice01.y, trianglePointCoord0.y) && !IsEqual(trianglePointCoord1.y, trianglePointCoord0.y)) { k01 = (newVertice01.y - trianglePointCoord0.y) / (trianglePointCoord1.y - trianglePointCoord0.y); } else { k01 = (newVertice01.z - trianglePointCoord0.z) / (trianglePointCoord1.z - trianglePointCoord0.z); } if (uvList.Count > 0) { Vector2 uv0 = uvList[trianglePointIndex0]; Vector2 uv1 = uvList[trianglePointIndex1]; float newUV_x = (uv1.x - uv0.x) * k01 + uv0.x; float newUV_y = (uv1.y - uv0.y) * k01 + uv0.y; uvList.Add(new Vector2(newUV_x, newUV_y)); Debug.Log("纹理坐标" + uvList[uvList.Count - 1]); } //法向量 Vector3 normalX0 = normalList[trianglePointIndex0]; Vector3 normalX1 = normalList[trianglePointIndex1]; float newNoramlX01 = (normalX1.x - normalX0.x) * k01 + normalX0.x; float newNoramlY01 = (normalX1.y - normalX0.y) * k01 + normalX0.y; float newNoramlZ01 = (normalX1.z - normalX0.z) * k01 + normalX0.z; normalList.Add(new Vector3(newNoramlX01, newNoramlY01, newNoramlZ01)); } //求得0-2与切平面的交点 Vector3 newVertice02 = GetLinePlaneCrossPoint(trianglePointCoord0, trianglePointCoord2); int index02 = IsContainsVertice(verticeList, newVertice02); if (index02 == -1 || !m_IsClearSamePoint) { verticeList.Add(newVertice02); index02 = verticeList.Count - 1; float k02 = 0; if (!IsEqual(newVertice02.x, trianglePointCoord0.x) && !IsEqual(trianglePointCoord2.x, trianglePointCoord0.x)) { k02 = (newVertice02.x - trianglePointCoord0.x) / (trianglePointCoord2.x - trianglePointCoord0.x); } else if (!IsEqual(newVertice02.y, trianglePointCoord0.y) && !IsEqual(trianglePointCoord2.y, trianglePointCoord0.y)) { k02 = (newVertice02.y - trianglePointCoord0.y) / (trianglePointCoord2.y - trianglePointCoord0.y); } else { k02 = (newVertice02.z - trianglePointCoord0.z) / (trianglePointCoord2.z - trianglePointCoord0.z); } if (uvList.Count > 0) { Vector2 uv0 = uvList[trianglePointIndex0]; Vector2 uv2 = uvList[trianglePointIndex2]; float newUV_x = (uv2.x - uv0.x) * k02 + uv0.x; float newUV_y = (uv2.y - uv0.y) * k02 + uv0.y; uvList.Add(new Vector2(newUV_x, newUV_y)); Debug.Log("纹理坐标" + uvList[uvList.Count - 1]); } //法向量 Vector3 normalX0 = normalList[trianglePointIndex0]; Vector3 normalX2 = normalList[trianglePointIndex2]; float newNoramlX02 = (normalX2.x - normalX0.x) * k02 + normalX0.x; float newNoramlY02 = (normalX2.y - normalX0.y) * k02 + normalX0.y; float newNoramlZ02 = (normalX2.z - normalX0.z) * k02 + normalX0.z; normalList.Add(new Vector3(newNoramlX02, newNoramlY02, newNoramlZ02)); } //插入顶点索引,以此构建新三角形 //{0} triangleList.Insert(triangleIndex + 1, index01); triangleList.Insert(triangleIndex + 2, index02); triangleList.Insert(triangleIndex + 3, index01); //{1} //{2} triangleList.Insert(triangleIndex + 6, trianglePointIndex2); triangleList.Insert(triangleIndex + 7, index02); triangleList.Insert(triangleIndex + 8, index01); triangleIndex += 9; } else { triangleIndex += 3; } } //Debug.Log("顶点数" + verticeList.Count); //Debug.Log("顶点索引数" + triangleList.Count); //筛选出切割面两侧的顶点索引 List <int> triangles1 = new List <int>(); List <int> triangles2 = new List <int>(); for (int triangleIndex = 0; triangleIndex < triangleList.Count; triangleIndex += 3) { int trianglePoint0 = triangleList[triangleIndex]; int trianglePoint1 = triangleList[triangleIndex + 1]; int trianglePoint2 = triangleList[triangleIndex + 2]; Vector3 point0 = verticeList[trianglePoint0]; Vector3 point1 = verticeList[trianglePoint1]; Vector3 point2 = verticeList[trianglePoint2]; //切割面 float dis0 = GetPointToClipPlaneDis(point0); float dis1 = GetPointToClipPlaneDis(point1); float dis2 = GetPointToClipPlaneDis(point2); if ((dis0 < 0 || IsEqual(dis0, 0)) && (dis1 < 0 || IsEqual(dis1, 0)) && (dis2 < 0 || IsEqual(dis2, 0))) { triangles1.Add(trianglePoint0); triangles1.Add(trianglePoint1); triangles1.Add(trianglePoint2); } else { triangles2.Add(trianglePoint0); triangles2.Add(trianglePoint1); triangles2.Add(trianglePoint2); } } //新生顶点数 int newVerticeCount = verticeList.Count - verticeCount; //再次添加一遍新增顶点,用于缝合切口 for (int newVerticeIndex = 0; newVerticeIndex < newVerticeCount; ++newVerticeIndex) { Vector3 newVertice = verticeList[verticeCount + newVerticeIndex]; Vector3 qiekouVertice = new Vector3(newVertice.x, newVertice.y, newVertice.z); verticeList.Add(qiekouVertice); //uv if (uvList.Count > 0) { Vector2 newUv = uvList[verticeCount + newVerticeIndex]; Vector2 qiekouUv = new Vector3(0.99f, 0.99f); uvList.Add(qiekouUv); } //法线 Vector3 newNormal = normalList[verticeCount + newVerticeIndex]; Vector3 qiekouNormal = new Vector3(newNormal.x, newNormal.y, newNormal.z); normalList.Add(qiekouNormal); } verticeCount = verticeCount + newVerticeCount; //重新排序新生成的顶点,按照角度 List <SortAngle> SortAngleList = new List <SortAngle>(); for (int verticeIndex = verticeCount + 1; verticeIndex < verticeList.Count; verticeIndex++) { //计算角度,以0-1为参照 Vector3 vec1to0 = verticeList[verticeCount + 1] - verticeList[verticeCount]; Vector3 indexTo0 = verticeList[verticeIndex] - verticeList[verticeCount]; float moIndexto0 = indexTo0.magnitude; float mo1to0 = vec1to0.magnitude; float dotRes = Vector3.Dot(indexTo0, vec1to0); if (moIndexto0 == 0.0f) { continue; } float angle = Mathf.Acos(dotRes / (mo1to0 * moIndexto0)); //Vector3.Angle(indexTo0.normalized, vec1to0.normalized); bool isExis = false; for (int i = 0; i < SortAngleList.Count; ++i) { //同样角度,距离近的被剔除 if (Mathf.Abs(SortAngleList[i].Angle * 180.0f / Mathf.PI - angle * 180.0f / Mathf.PI) < 0.1f) { float dis1 = Vector3.Distance(verticeList[SortAngleList[i].Index], verticeList[verticeCount]); float dis2 = Vector3.Distance(verticeList[verticeIndex], verticeList[verticeCount]); if (dis2 >= dis1) { SortAngleList[i].Index = verticeIndex; } isExis = true; break; } } if (!isExis) { //Debug.Log(angle); SortAngle sortAngle = new SortAngle(); sortAngle.Index = verticeIndex; sortAngle.Angle = angle; SortAngleList.Add(sortAngle); } } SortAngleList.Sort(); //缝合切口 for (int verticeIndex = 0; verticeIndex < SortAngleList.Count - 1;) { triangles1.Add(SortAngleList[verticeIndex + 1].Index); triangles1.Add(SortAngleList[verticeIndex].Index); triangles1.Add(verticeCount); triangles2.Add(verticeCount); triangles2.Add(SortAngleList[verticeIndex].Index); triangles2.Add(SortAngleList[verticeIndex + 1].Index); verticeIndex++; } mf.mesh.vertices = verticeList.ToArray(); mf.mesh.triangles = triangles1.ToArray(); if (uvList.Count > 0) { mf.mesh.uv = uvList.ToArray(); } mf.mesh.normals = normalList.ToArray(); //分割模型 GameObject newModel = new GameObject("New Model"); MeshFilter meshFilter = newModel.AddComponent <MeshFilter>(); meshFilter.mesh.vertices = mf.mesh.vertices; meshFilter.mesh.triangles = triangles2.ToArray(); meshFilter.mesh.uv = mf.mesh.uv; meshFilter.mesh.normals = mf.mesh.normals; Renderer newRenderer = newModel.AddComponent <MeshRenderer>(); newRenderer.material = this.gameObject.GetComponent <MeshRenderer>().material; newModel.transform.localPosition = transform.localPosition; newModel.AddComponent <TouchToPlane>(); }
/// This option has a far longer preprocessing time at startup but leads to better runtime performance. void Start() { Component[] filters = GetComponentsInChildren(typeof(MeshFilter)); Matrix4x4 myTransform = transform.worldToLocalMatrix; Hashtable materialToMesh = new Hashtable(); for (int i = 0; i < filters.Length; i++) { MeshFilter filter = (MeshFilter)filters[i]; Renderer curRenderer = filters[i].renderer; MeshCombineUtility.MeshInstance instance = new MeshCombineUtility.MeshInstance(); instance.mesh = filter.sharedMesh; if (curRenderer != null && curRenderer.enabled && instance.mesh != null) { instance.transform = myTransform * filter.transform.localToWorldMatrix; Material[] materials = curRenderer.sharedMaterials; for (int m = 0; m < materials.Length; m++) { instance.subMeshIndex = System.Math.Min(m, instance.mesh.subMeshCount - 1); ArrayList objects = (ArrayList)materialToMesh[materials[m]]; if (objects != null) { objects.Add(instance); } else { objects = new ArrayList(); objects.Add(instance); materialToMesh.Add(materials[m], objects); } } curRenderer.enabled = false; } } foreach (DictionaryEntry de in materialToMesh) { ArrayList elements = (ArrayList)de.Value; MeshCombineUtility.MeshInstance[] instances = (MeshCombineUtility.MeshInstance[])elements.ToArray(typeof(MeshCombineUtility.MeshInstance)); // We have a maximum of one material, so just attach the mesh to our own game object if (materialToMesh.Count == 1) { // Make sure we have a mesh filter & renderer if (GetComponent(typeof(MeshFilter)) == null) { gameObject.AddComponent(typeof(MeshFilter)); } if (!GetComponent("MeshRenderer")) { gameObject.AddComponent("MeshRenderer"); } MeshFilter filter = (MeshFilter)GetComponent(typeof(MeshFilter)); filter.mesh = MeshCombineUtility.Combine(instances, generateTriangleStrips); renderer.material = (Material)de.Key; renderer.enabled = true; } // We have multiple materials to take care of, build one mesh / gameobject for each material // and parent it to this object else { GameObject go = new GameObject("Combined mesh"); go.transform.parent = transform; go.transform.localScale = Vector3.one; go.transform.localRotation = Quaternion.identity; go.transform.localPosition = Vector3.zero; go.layer = gameObject.layer; go.AddComponent(typeof(MeshFilter)); go.AddComponent("MeshRenderer"); go.renderer.material = (Material)de.Key; MeshFilter filter = (MeshFilter)go.GetComponent(typeof(MeshFilter)); filter.mesh = MeshCombineUtility.Combine(instances, generateTriangleStrips); } } }
private void DrawGridMesh(int gz, int gx) { GameObject go = _grid_go[gz * _generator._data_col + gx]; MeshFilter mf = go.GetComponent <MeshFilter>(); Mesh mMesh = new Mesh(); mMesh.hideFlags = HideFlags.DontSave; mMesh.name = go.name; List <Vector3> verts = new List <Vector3>(); List <Vector2> uvs = new List <Vector2>(); List <Color32> cols = new List <Color32>(); List <int> indecies = new List <int>(); int index = 0; for (int z = 0; z < 32; z++) { for (int x = 0; x < 32; x++) { if (z + 32 * gz < _generator._row && x + 32 * gx < _generator._col) { int debug = _generator._col * 32 * gz + _generator._col * z + gx * 32 + x; float height = _generator.GetHeight(debug); float pos_x = _generator._min.x + gx * 32 * _generator._grid_size + x * _generator._grid_size; float pos_y = _generator._min.y + height + 0.02f; float pos_z = _generator._min.z + gz * 32 * _generator._grid_size + z * _generator._grid_size; verts.Add(new Vector3(pos_x, pos_y, pos_z)); verts.Add(new Vector3(pos_x, pos_y, pos_z + _generator._grid_size * 0.95f)); verts.Add(new Vector3(pos_x + _generator._grid_size * 0.95f, pos_y, pos_z + _generator._grid_size * 0.95f)); verts.Add(new Vector3(pos_x + _generator._grid_size * 0.95f, pos_y, pos_z)); indecies.Add(index); indecies.Add(index + 1); indecies.Add(index + 2); indecies.Add(index + 2); indecies.Add(index + 3); indecies.Add(index); index += 4; uvs.Add(new Vector2(0f, 0f)); uvs.Add(new Vector2(0f, 1f)); uvs.Add(new Vector2(1f, 1f)); uvs.Add(new Vector2(1f, 0f)); Color color = height < 0 ? Color.red : Color.green; cols.Add(color); cols.Add(color); cols.Add(color); cols.Add(color); } } } mMesh.vertices = verts.ToArray(); mMesh.triangles = indecies.ToArray(); mMesh.uv = uvs.ToArray(); mMesh.colors32 = cols.ToArray(); mf.mesh = mMesh; }
public virtual void Reset() { if (meshFilter != null) { meshFilter.sharedMesh = null; } meshRenderer = GetComponent <MeshRenderer>(); if (meshRenderer != null) { meshRenderer.sharedMaterial = null; } if (mesh1 != null) { if (Application.isPlaying) { Destroy(mesh1); } else { DestroyImmediate(mesh1); } } if (mesh2 != null) { if (Application.isPlaying) { Destroy(mesh2); } else { DestroyImmediate(mesh2); } } lastState = new LastState(); mesh1 = null; mesh2 = null; vertices = null; colors = null; uvs = null; sharedMaterials = new Material[0]; submeshMaterials.Clear(); submeshes.Clear(); skeleton = null; valid = false; if (!skeletonDataAsset) { if (logErrors) { Debug.LogError("Missing SkeletonData asset.", this); } return; } SkeletonData skeletonData = skeletonDataAsset.GetSkeletonData(false); if (skeletonData == null) { return; } valid = true; meshFilter = GetComponent <MeshFilter>(); meshRenderer = GetComponent <MeshRenderer>(); mesh1 = newMesh(); mesh2 = newMesh(); vertices = new Vector3[0]; skeleton = new Skeleton(skeletonData); if (initialSkinName != null && initialSkinName.Length > 0 && initialSkinName != "default") { skeleton.SetSkin(initialSkinName); } submeshSeparatorSlots.Clear(); for (int i = 0; i < submeshSeparators.Length; i++) { submeshSeparatorSlots.Add(skeleton.FindSlot(submeshSeparators[i])); } CollectSubmeshRenderers(); LateUpdate(); if (OnReset != null) { OnReset(this); } }
// Packs all billboards into single mesh private void CreateMesh() { // Using half way between forward and up for billboard normal // Workable for most lighting but will need a better system eventually Vector3 normalTemplate = Vector3.Normalize(Vector3.up + Vector3.forward); // Create billboard data // Serializing UV array creates less garbage than recreating every time animation ticks Bounds newBounds = new Bounds(); int vertexCount = billboardItems.Count * vertsPerQuad; int indexCount = billboardItems.Count * indicesPerQuad; Vector3[] vertices = new Vector3[vertexCount]; Vector3[] normals = new Vector3[vertexCount]; Vector4[] tangents = new Vector4[vertexCount]; uvs = new Vector2[vertexCount]; int[] indices = new int[indexCount]; int currentIndex = 0; for (int billboard = 0; billboard < billboardItems.Count; billboard++) { int offset = billboard * vertsPerQuad; BillboardItem bi = billboardItems[billboard]; // Billboard size and origin Vector2 finalSize = GetScaledBillboardSize(bi.record); //float hx = (finalSize.x / 2); float hy = (finalSize.y / 2); Vector3 position = bi.position + new Vector3(0, hy, 0); // Billboard UVs Rect rect = cachedMaterial.atlasRects[cachedMaterial.atlasIndices[bi.record].startIndex + bi.currentFrame]; uvs[offset] = new Vector2(rect.x, rect.yMax); uvs[offset + 1] = new Vector2(rect.xMax, rect.yMax); uvs[offset + 2] = new Vector2(rect.x, rect.y); uvs[offset + 3] = new Vector2(rect.xMax, rect.y); // Tangent data for shader is used to size billboard tangents[offset] = new Vector4(finalSize.x, finalSize.y, 0, 1); tangents[offset + 1] = new Vector4(finalSize.x, finalSize.y, 1, 1); tangents[offset + 2] = new Vector4(finalSize.x, finalSize.y, 0, 0); tangents[offset + 3] = new Vector4(finalSize.x, finalSize.y, 1, 0); // Other data for shader for (int vertex = 0; vertex < vertsPerQuad; vertex++) { vertices[offset + vertex] = position; normals[offset + vertex] = normalTemplate; } // Assign index data indices[currentIndex] = offset; indices[currentIndex + 1] = offset + 1; indices[currentIndex + 2] = offset + 2; indices[currentIndex + 3] = offset + 3; indices[currentIndex + 4] = offset + 2; indices[currentIndex + 5] = offset + 1; currentIndex += indicesPerQuad; // Update bounds tracking using actual position and size // This can be a little wonky with single billboards side-on as AABB does not rotate // But it generally works well for large batches as intended // Multiply finalSize * 2f if culling problems with standalone billboards Bounds currentBounds = new Bounds(position, finalSize); newBounds.Encapsulate(currentBounds); } // Create mesh if (billboardMesh == null) { // New mesh billboardMesh = new Mesh(); billboardMesh.name = "BillboardBatchMesh"; } else { // Existing mesh if (billboardMesh.vertexCount == vertices.Length) billboardMesh.Clear(true); // Same vertex layout else billboardMesh.Clear(false); // New vertex layout } // Assign mesh data billboardMesh.vertices = vertices; // Each vertex is positioned at billboard origin billboardMesh.tangents = tangents; // Tangent stores corners and size billboardMesh.triangles = indices; // Standard indices billboardMesh.normals = normals; // Standard normals billboardMesh.uv = uvs; // Standard uv coordinates into atlas // Manually update bounds to account for max billboard height billboardMesh.bounds = newBounds; // Assign mesh MeshFilter filter = GetComponent<MeshFilter>(); filter.sharedMesh = billboardMesh; }
/// <summary> /// Creates mesh and material for this enemy. /// </summary> /// <param name="dfUnity">DaggerfallUnity singleton. Required for content readers and settings.</param> /// <param name="archive">Texture archive index derived from type and gender.</param> private void AssignMeshAndMaterial(DaggerfallUnity dfUnity, int archive) { // Get mesh filter if (meshFilter == null) { meshFilter = GetComponent <MeshFilter>(); } // Vertices for a 1x1 unit quad // This is scaled to correct size depending on facing and orientation float hx = 0.5f, hy = 0.5f; Vector3[] vertices = new Vector3[4]; vertices[0] = new Vector3(hx, hy, 0); vertices[1] = new Vector3(-hx, hy, 0); vertices[2] = new Vector3(hx, -hy, 0); vertices[3] = new Vector3(-hx, -hy, 0); // Indices int[] indices = new int[6] { 0, 1, 2, 3, 2, 1, }; // Normals Vector3 normal = Vector3.Normalize(Vector3.up + Vector3.forward); Vector3[] normals = new Vector3[4]; normals[0] = normal; normals[1] = normal; normals[2] = normal; normals[3] = normal; // Create mesh Mesh mesh = new Mesh(); mesh.name = string.Format("MobileEnemyMesh"); mesh.vertices = vertices; mesh.triangles = indices; mesh.normals = normals; // Assign mesh meshFilter.sharedMesh = mesh; // Create material Material material = TextureReplacement.GetMobileBillboardMaterial(archive, GetComponent <MeshFilter>(), ref summary.ImportedTextures) ?? dfUnity.MaterialReader.GetMaterialAtlas( archive, 0, 4, 1024, out summary.AtlasRects, out summary.AtlasIndices, 4, true, 0, false, true); // Set new enemy material GetComponent <MeshRenderer>().sharedMaterial = material; }
/// <summary> /// Sets enemy orientation index. /// </summary> /// <param name="orientation">New orientation index.</param> private void OrientEnemy(int orientation) { if (summary.StateAnims == null || summary.StateAnims.Length == 0) { return; } // Get mesh filter if (meshFilter == null) { meshFilter = GetComponent <MeshFilter>(); } // Try to fix if anim array is null if (summary.StateAnims == null) { ApplyEnemyState(); } // Get enemy size and scale for this state int record = summary.StateAnims[orientation].Record; summary.AnimStateRecord = record; Vector2 size = summary.RecordSizes[record]; // Post-fix female texture scale for 475 while casting spells // The scale read from Daggerfall's files is too small if (summary.Enemy.FemaleTexture == 475 && summary.Enemy.Gender == MobileGender.Female && record >= 20 && record <= 24) { size *= 1.35f; } // Ensure walking enemies keep their feet aligned between states if (summary.Enemy.Behaviour != MobileBehaviour.Flying && summary.Enemy.Behaviour != MobileBehaviour.Aquatic && summary.EnemyState != MobileStates.Idle) { Vector2 idleSize = summary.RecordSizes[0]; transform.localPosition = new Vector3(0f, (size.y - idleSize.y) * 0.5f, 0f); } else { transform.localPosition = Vector3.zero; } // Set mesh scale for this state transform.localScale = new Vector3(size.x, size.y, 1); // Check if orientation flip needed bool flip = summary.StateAnims[orientation].FlipLeftRight; // Scorpion animations need to be inverted if (summary.Enemy.ID == (int)MobileTypes.GiantScorpion) { flip = !flip; } // Update Record/Frame texture if (summary.ImportedTextures.HasImportedTextures) { if (meshRenderer == null) { meshRenderer = GetComponent <MeshRenderer>(); } // Assign imported texture meshRenderer.material.mainTexture = summary.ImportedTextures.Albedo[record][currentFrame]; if (summary.ImportedTextures.IsEmissive) { meshRenderer.material.SetTexture(Uniforms.EmissionMap, summary.ImportedTextures.EmissionMaps[record][currentFrame]); } // Update UVs on mesh Vector2[] uvs = new Vector2[4]; if (flip) { uvs[0] = new Vector2(1, 1); uvs[1] = new Vector2(0, 1); uvs[2] = new Vector2(1, 0); uvs[3] = new Vector2(0, 0); } else { uvs[0] = new Vector2(0, 1); uvs[1] = new Vector2(1, 1); uvs[2] = new Vector2(0, 0); uvs[3] = new Vector2(1, 0); } meshFilter.sharedMesh.uv = uvs; } else { // Daggerfall Atlas: Update UVs on mesh Rect rect = summary.AtlasRects[summary.AtlasIndices[record].startIndex + currentFrame]; Vector2[] uvs = new Vector2[4]; if (flip) { uvs[0] = new Vector2(rect.xMax, rect.yMax); uvs[1] = new Vector2(rect.x, rect.yMax); uvs[2] = new Vector2(rect.xMax, rect.y); uvs[3] = new Vector2(rect.x, rect.y); } else { uvs[0] = new Vector2(rect.x, rect.yMax); uvs[1] = new Vector2(rect.xMax, rect.yMax); uvs[2] = new Vector2(rect.x, rect.y); uvs[3] = new Vector2(rect.xMax, rect.y); } meshFilter.sharedMesh.uv = uvs; } // Assign new orientation lastOrientation = orientation; }
public void Rebuild() { //height = distance * 3; //create the mesh modelMesh = new Mesh(); modelMesh.name = "ProceduralPlaneMesh"; meshFilter = gameObject.GetComponent <MeshFilter>(); meshFilter.mesh = modelMesh; //sanity check if (xSegments < MIN_X_SEGMENTS) { xSegments = MIN_X_SEGMENTS; } if (ySegments < MIN_Y_SEGMENTS) { ySegments = MIN_Y_SEGMENTS; } //calculate how many vertices we need numVertexColumns = xSegments + 1; numVertexRows = ySegments + 1; //calculate sizes int numVertices = numVertexColumns * numVertexRows; int numUVs = numVertices; //always int numTris = xSegments * ySegments * 2; //fact int trisArrayLength = numTris * 3; //3 places in the array for each tri // log the number of tris //Logger.Info ("Plane has " + trisArrayLength/3 + " tris"); //initialize arrays Vector3[] Vertices = new Vector3[numVertices]; Vector2[] UVs = new Vector2[numUVs]; int[] Tris = new int[trisArrayLength]; //precalculate increments float xStep = width / xSegments; float yStep = height / ySegments; float uvStepH = 1.0f / xSegments; // place UVs evenly float uvStepV = 1.0f / ySegments; float xOffset = -width / 2f; // this offset means we want the pivot at the center float yOffset = -height / 2f; // same as above float radSpan = angleSpan * Mathf.PI / 180; float mSpan = 1; float aspect = (float)Screen.width / Screen.height; float m2rad = radSpan / mSpan; for (int j = 0; j < numVertexRows; j++) { for (int i = 0; i < numVertexColumns; i++) { // calculate some weights for the "keystone" vertex pull // for some reason this doesn't work // TODO: fix this to cache values and make it faster //float bottomLeftWeight = ((numVertexColumns-1)-i)/(numVertexColumns-1) * ((numVertexRows-1)-j)/(numVertexRows-1); // position current vertex // these offsets are too ridiculous to even try to explain // ok trying: basically each vertex we drag is affected by the offsets on the 4 courners but // the weight of that effect is linearly inverse analogous to the distance from that corner Vector3 p = new Vector3( i * xStep + xOffset + bottomLeftOffset.x * ((numVertexColumns - 1) - i) / (numVertexColumns - 1) * ((numVertexRows - 1) - j) / (numVertexRows - 1) + bottomRightOffset.x * i / (numVertexColumns - 1) * ((numVertexRows - 1) - j) / (numVertexRows - 1) + topLeftOffset.x * ((numVertexColumns - 1) - i) / (numVertexColumns - 1) * j / (numVertexRows - 1) + topRightOffset.x * i / (numVertexColumns - 1) * j / (numVertexRows - 1), j * yStep + yOffset + bottomLeftOffset.y * ((numVertexColumns - 1) - i) / (numVertexColumns - 1) * ((numVertexRows - 1) - j) / (numVertexRows - 1) + bottomRightOffset.y * i / (numVertexColumns - 1) * ((numVertexRows - 1) - j) / (numVertexRows - 1) + topLeftOffset.y * ((numVertexColumns - 1) - i) / (numVertexColumns - 1) * j / (numVertexRows - 1) + topRightOffset.y * i / (numVertexColumns - 1) * j / (numVertexRows - 1) - ((height - 1) / 2), distance ); float nx = Mathf.Lerp((aspect * height) * p.x, Mathf.Cos(Mathf.PI / 2 - p.x * m2rad) * distance, Mathf.Clamp01(curviness)); float z = Mathf.Sin(Mathf.PI / 2 - p.x * m2rad * Mathf.Clamp01(curviness)); int index = j * numVertexColumns + i; //Logger.Info(90 - x * m2angle); Vertices[index] = new Vector3(nx, p.y, z); if (curviness > 1) { float roundness = curviness - 1; Vertices[index] = Vector3.Lerp(Vertices[index], Vertices[index].normalized * distance, Mathf.Clamp01(roundness)); // Logger.Info(roundness); } //calculate UVs UVs[index] = new Vector2(i * uvStepH, j * uvStepV); //create the tris if (j == 0 || i >= numVertexColumns - 1) { continue; } else { // For every vertex we draw 2 tris in this for-loop, therefore we need 2*3=6 indices in the Tris array int baseIndex = (j - 1) * xSegments * 6 + i * 6; //1st tri - below and in front Tris[baseIndex + 0] = j * numVertexColumns + i; Tris[baseIndex + 1] = j * numVertexColumns + i + 1; Tris[baseIndex + 2] = (j - 1) * numVertexColumns + i; //2nd tri - the one it doesn't touch Tris[baseIndex + 3] = (j - 1) * numVertexColumns + i; Tris[baseIndex + 4] = j * numVertexColumns + i + 1; Tris[baseIndex + 5] = (j - 1) * numVertexColumns + i + 1; } } } // assign vertices, uvs and tris modelMesh.Clear(); modelMesh.vertices = Vertices; modelMesh.uv = UVs; modelMesh.triangles = Tris; modelMesh.RecalculateNormals(); modelMesh.RecalculateBounds(); }
public void BuildMesh() { map = new TileMapData(size_x, size_z); int numTiles = size_x * size_z; int numTris = numTiles * 2; int vsize_x = size_x + 1; int vsize_z = size_z + 1; int numVerts = vsize_x * vsize_z; // Generate the mesh data Vector3[] vertices = new Vector3[numVerts]; Vector3[] normals = new Vector3[numVerts]; Vector2[] uv = new Vector2[numVerts]; int[] triangles = new int[numTris * 3]; int x, z; for (z = 0; z < vsize_z; z++) { for (x = 0; x < vsize_x; x++) { vertices[z * vsize_x + x] = new Vector3(x * tileSize, 0, z * tileSize); if (z < size_z && x < size_x) { map.GetTile(x, z).SetWorldPos(vertices[z * vsize_x + x] + new Vector3(0.5f, -0.5f, 0.5f)); } normals[z * vsize_x + x] = Vector3.up; uv[z * vsize_x + x] = new Vector2((float)x / size_x, 1f - (float)z / size_z); } } //Debug.Log("Done Verts!"); for (z = 0; z < size_z; z++) { for (x = 0; x < size_x; x++) { int squareIndex = z * size_x + x; int triOffset = squareIndex * 6; //triangles[triOffset + 0] = z * vsize_x + x + 0; //triangles[triOffset + 2] = z * vsize_x + x + vsize_x + 0; //triangles[triOffset + 1] = z * vsize_x + x + vsize_x + 1; //triangles[triOffset + 3] = z * vsize_x + x + 0; //triangles[triOffset + 5] = z * vsize_x + x + vsize_x + 1; //triangles[triOffset + 4] = z * vsize_x + x + 1; triangles[triOffset + 0] = z * vsize_x + x + 0; triangles[triOffset + 1] = z * vsize_x + x + vsize_x + 0; triangles[triOffset + 2] = z * vsize_x + x + vsize_x + 1; triangles[triOffset + 3] = z * vsize_x + x + 0; triangles[triOffset + 4] = z * vsize_x + x + vsize_x + 1; triangles[triOffset + 5] = z * vsize_x + x + 1; } } //Debug.Log("Done Triangles!"); // Create a new Mesh and populate with the data Mesh mesh = new Mesh(); mesh.vertices = vertices; mesh.triangles = triangles; mesh.normals = normals; mesh.uv = uv; // Assign our mesh to our filter/renderer/collider MeshFilter mesh_filter = GetComponent <MeshFilter>(); MeshCollider mesh_collider = GetComponent <MeshCollider>(); mesh_filter.mesh = mesh; mesh_collider.sharedMesh = mesh; //Debug.Log("Done Mesh!"); BuildTexture(); }
protected virtual void DrawInspectorGUI() { SkeletonRenderer component = (SkeletonRenderer)target; EditorGUILayout.BeginHorizontal(); EditorGUILayout.PropertyField(skeletonDataAsset); const string ReloadButtonLabel = "Reload"; float reloadWidth = GUI.skin.label.CalcSize(new GUIContent(ReloadButtonLabel)).x + 20; if (GUILayout.Button(ReloadButtonLabel, GUILayout.Width(reloadWidth))) { if (component.skeletonDataAsset != null) { foreach (AtlasAsset aa in component.skeletonDataAsset.atlasAssets) { if (aa != null) { aa.Reset(); } } component.skeletonDataAsset.Reset(); } component.Initialize(true); } EditorGUILayout.EndHorizontal(); if (!component.valid) { component.Initialize(true); component.LateUpdate(); if (!component.valid) { return; } } #if NO_PREFAB_MESH if (meshFilter == null) { meshFilter = component.GetComponent <MeshFilter>(); } if (isInspectingPrefab) { meshFilter.sharedMesh = null; } #endif // Initial skin name. { String[] skins = new String[component.skeleton.Data.Skins.Count]; int skinIndex = 0; for (int i = 0; i < skins.Length; i++) { String skinNameString = component.skeleton.Data.Skins.Items[i].Name; skins[i] = skinNameString; if (skinNameString == initialSkinName.stringValue) { skinIndex = i; } } skinIndex = EditorGUILayout.Popup("Initial Skin", skinIndex, skins); initialSkinName.stringValue = skins[skinIndex]; } EditorGUILayout.Space(); // Sorting Layers { SpineInspectorUtility.SortingPropertyFields(sortingProperties, applyModifiedProperties: true); } // More Render Options... { using (new EditorGUILayout.VerticalScope(EditorStyles.helpBox)) { EditorGUI.indentLevel++; advancedFoldout = EditorGUILayout.Foldout(advancedFoldout, "Advanced"); if (advancedFoldout) { EditorGUI.indentLevel++; SeparatorsField(separatorSlotNames); EditorGUILayout.PropertyField(meshes, new GUIContent("Render Mesh Attachments", "Disable to optimize rendering for skeletons that don't use Mesh Attachments")); EditorGUILayout.PropertyField(immutableTriangles, new GUIContent("Immutable Triangles", "Enable to optimize rendering for skeletons that never change attachment visbility")); EditorGUILayout.Space(); const float MinZSpacing = -0.1f; const float MaxZSpacing = 0f; EditorGUILayout.Slider(zSpacing, MinZSpacing, MaxZSpacing); // Optional fields. May be disabled in SkeletonRenderer. if (normals != null) { EditorGUILayout.PropertyField(normals); EditorGUILayout.PropertyField(tangents); } if (frontFacing != null) { EditorGUILayout.PropertyField(frontFacing); } EditorGUI.indentLevel--; } EditorGUI.indentLevel--; } } }
public void UpdateHexVisuals() { for (int column = 0; column < numColumns; column++) { for (int row = 0; row < numRows; row++) { Hex h = hexes[column, row]; GameObject hexGO = hexToGameObjectMap[h]; HexComponent hexComp = hexGO.GetComponentInChildren <HexComponent>(); MeshRenderer mr = hexGO.GetComponentInChildren <MeshRenderer>(); MeshFilter mf = hexGO.GetComponentInChildren <MeshFilter>(); //Reset the movement since we start with ocean then repaint //Moisture if (h.Elevation >= HeightFlat && h.Elevation < HeightMountain) //No mountains with trees { if (h.Moisture >= MoistureJungle) { mr.material = MatGrassland; h.TerrainType = Hex.TERRAIN_TYPE.GRASSLANDS; h.FeatureType = Hex.FEATURE_TYPE.RAINFOREST; Vector3 p = hexGO.transform.position; if (h.Elevation >= HeightHill) { p.y += 0.1f; } GameObject.Instantiate(JunglePrefab, p, Quaternion.identity, hexGO.transform); } else if (h.Moisture >= MoistureForest) { mr.material = MatGrassland; h.TerrainType = Hex.TERRAIN_TYPE.GRASSLANDS; h.FeatureType = Hex.FEATURE_TYPE.FOREST; //Spawn trees Vector3 p = hexGO.transform.position; if (h.Elevation >= HeightHill) { p.y += 0.1f; } h.FeatureType = Hex.FEATURE_TYPE.FOREST; GameObject.Instantiate(ForestPrefab, p, Quaternion.identity, hexGO.transform); } else if (h.Moisture >= MoistureGrasslands) { mr.material = MatGrassland; h.TerrainType = Hex.TERRAIN_TYPE.GRASSLANDS; } else if (h.Moisture >= MoisturePlains) { mr.material = MatPlain; h.TerrainType = Hex.TERRAIN_TYPE.PLAINS; } else { mr.material = MatDesert; h.TerrainType = Hex.TERRAIN_TYPE.DESERT; } } //Elevation if (h.Elevation >= HeightMountain) { mr.material = MatMountain; mf.mesh = MeshMountain; h.ElevationType = Hex.ELEVATION_TYPE.MOUNTAIN; } else if (h.Elevation >= HeightHill) { mf.mesh = MeshHill; h.ElevationType = Hex.ELEVATION_TYPE.HILL; hexComp.VerticalOffset = 0.25f; Vector3 p = hexGO.transform.position; if (h.Elevation >= HeightHill) { p.y += 0.1f; } GameObject.Instantiate(HillPrefab, p, Quaternion.identity, hexGO.transform); } else if (h.Elevation >= HeightFlat) { mf.mesh = MeshGrassland; h.ElevationType = Hex.ELEVATION_TYPE.FLAT; } else { mr.material = MatOcean; mf.mesh = MeshWater; h.ElevationType = Hex.ELEVATION_TYPE.SHALLOWWATER; } //Set the hex label hexGO.transform.GetChild(1).GetComponent <TextMeshPro>().text = string.Format("{0},{1}\n{2}", column, row, h.BaseMovementCost(false, false, false, false, false)); } } }
public void Init(Factory factory) { renderers = new List<IMeshRenderer>(); mesh = new Mesh(); mesh.name = "LWF/" + factory.data.name; mesh.MarkDynamic(); meshFilter = gameObject.AddComponent<MeshFilter>(); meshFilter.sharedMesh = mesh; meshRenderer = gameObject.AddComponent<UnityEngine.MeshRenderer>(); if (!string.IsNullOrEmpty(factory.sortingLayerName)) meshRenderer.sortingLayerName = factory.sortingLayerName; meshRenderer.sortingOrder = factory.sortingOrder; meshRenderer.castShadows = false; meshRenderer.receiveShadows = false; buffer = new CombinedMeshBuffer(); }
public Vector3 v7 = new Vector3(-0.5f, 0.5f, -0.5f); //left (top, back, left) void Start() { MeshFilter meshFilter = GetComponent <MeshFilter>(); if (meshFilter == null) { Debug.LogError("MeshFilter not found!"); return; } Mesh mesh = meshFilter.sharedMesh; if (mesh == null) { meshFilter.mesh = new Mesh(); mesh = meshFilter.sharedMesh; } mesh.Clear(); // Vector3 v0 = new Vector3 (-length, -length, length ); //left (bottom, front, left) // Vector3 v1 = new Vector3 (length, -length, length ); //right (bottom, front, right) // Vector3 v2 = new Vector3 (length , -length, -length); //right (bottom, back, right) // Vector3 v3 = new Vector3 (-length , -length , -length); //left (bottom, back, left) // Vector3 v4 = new Vector3 (-length, length, length ); //left (top, front, left) // Vector3 v5 = new Vector3 (length, length, length ); //right (top, front, right) // Vector3 v6 = new Vector3 (length , length, -length); //right (top, back, right) // Vector3 v7 = new Vector3 (-length , length, -length); //left (top, back, left) mesh.vertices = new Vector3[] { // Front face v4, v5, v0, v1, // Back face v6, v7, v2, v3, // Left face v7, v4, v3, v0, // Right face v5, v6, v1, v2, // Top face v7, v6, v4, v5, // Bottom face v0, v1, v3, v2 }; //Add Triangles region //these are three point, and work clockwise to determine what side is visible mesh.triangles = new int[] { //front face 0, 2, 3, // first triangle 3, 1, 0, // second triangle //back face 4, 6, 7, // first triangle 7, 5, 4, // second triangle //left face 8, 10, 11, // first triangle 11, 9, 8, // second triangle //right face 12, 14, 15, // first triangle 15, 13, 12, // second triangle //top face 16, 18, 19, // first triangle 19, 17, 16, // second triangle //bottom face 20, 22, 23, // first triangle 23, 21, 20, // second triangle }; //Add Normales region Vector3 front = Vector3.forward; Vector3 back = Vector3.back; Vector3 left = Vector3.left; Vector3 right = Vector3.right; Vector3 up = Vector3.up; Vector3 down = Vector3.down; mesh.normals = new Vector3[] { // Front face front, front, front, front, // Back face back, back, back, back, // Left face left, left, left, left, // Right face right, right, right, right, // Top face up, up, up, up, // Bottom face down, down, down, down }; //end Normales region //Add UVs region Vector2 u00 = new Vector2(0f, 0f); Vector2 u10 = new Vector2(1f, 0f); Vector2 u01 = new Vector2(0f, 1f); Vector2 u11 = new Vector2(1f, 1f); Vector2[] uvs = new Vector2[] { // Front face uv u01, u00, u11, u10, // Back face uv u01, u00, u11, u10, // Left face uv u01, u00, u11, u10, // Right face uv u01, u00, u11, u10, // Top face uv u01, u00, u11, u10, // Bottom face uv u01, u00, u11, u10 }; //End UVs region mesh.RecalculateNormals(); mesh.RecalculateBounds(); mesh.Optimize(); MeshRenderer renderer = GetComponent <MeshRenderer> (); Material material = new Material(Shader.Find("Standard")); Color color = new Color(Random.value, Random.value, Random.value, 1.0f); renderer.material.color = color; // GetComponent<MeshCollider>().sharedMesh = null; // MeshCollider mCollider = GetComponent<MeshCollider> (); // mCollider.sharedMesh = mesh; }
internal static void NameGameObject(IEnumerable <Object> targets) { //sb用来生成代码并复制到剪贴板 StringBuilder sb = new StringBuilder(128); foreach (Object item in targets) { Transform t = item as Transform; Component[] coms = t.GetComponents <Component>(); //没有Image的话 if (coms.Length > 1) //只有Transform的话排除 { Undo.RecordObject(t.gameObject, "Rename"); Component com = coms[1]; Type comType = com.GetType(); if (comType == typeof(SpriteRenderer)) { SpriteRenderer sr = com as SpriteRenderer; if (sr.sprite) { t.name = "sp" + sr.sprite.name; } else { t.name = "spNull"; } } #if UNITY_2017_1_OR_NEWER else if (comType == typeof(PlayableDirector)) { PlayableDirector pd = com as PlayableDirector; t.name = pd.playableAsset ? pd.playableAsset.name : "PlayableDirector"; } #endif else if (comType == typeof(ParticleSystem)) { ParticleSystemRenderer component = com.GetComponent <ParticleSystemRenderer>(); if (component.sharedMaterial) { t.name = "ps" + component.sharedMaterial.name; } } else if (comType == typeof(Light)) { t.name = (com as Light).type + " light"; } else if (comType == typeof(MeshFilter)) { MeshFilter meshFilter = com as MeshFilter; if (meshFilter.sharedMesh) { t.name = meshFilter.sharedMesh.name; } } else { MethodInfo methodInfo = comType.GetMethod("Name", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); if (methodInfo == null) { t.name = comType.Name; return; } methodInfo.Invoke(t, null); } string strType = comType.Name; string strValue = strType[0].ToString().ToLower() + strType.Substring(1); sb.Append("public ").Append(strType).Append(" ").Append(strValue).AppendLine(";"); } if (Event.current.alt) { t.name = $"{t.name} ({t.GetSiblingIndex()})"; } } GUIUtility.systemCopyBuffer = sb.ToString(); }
/* * MIT License * * Copyright (c) 2019 UnityMeshImporter - Dongho Kang * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal * in the Software without restriction, including without limitation the rights * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell * copies of the Software, and to permit persons to whom the Software is * furnished to do so, subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE * SOFTWARE. */ /*CHANGES BY KITBASHERY: * * -Enabled realtime postprocess by default. * -Disabled loading textures by default. * -Changed finding standard shader with a material definded in the editor. * -Removed redundant GetComponent calls during component creation. * -Disabled recive shadows. * -Added Import class. * -Load function now returns an Import. */ private Import Load(string meshPath, float scaleX = 1, float scaleY = 1, float scaleZ = 1, bool loadTextures = false, bool fromLibrary = false) { if (!File.Exists(meshPath)) { return(null); } AssimpContext importer = new AssimpContext(); Scene scene = importer.ImportFile(meshPath, (PostProcessSteps.GenerateSmoothNormals | PostProcessSteps.Triangulate | PostProcessSteps.SortByPrimitiveType)); scene.SceneFlags = new SceneFlags(); if (scene == null) { return(null); } string parentDir = Directory.GetParent(meshPath).FullName; // Materials List <UnityEngine.Material> uMaterials = new List <Material>(); if (scene.HasMaterials) { foreach (var m in scene.Materials) { UnityEngine.Material uMaterial = defaultMaterial;//new UnityEngine.Material(Shader.Find("Standard")); if (loadTextures == true) { // Albedo if (m.HasColorDiffuse) { Color color = new Color( m.ColorDiffuse.R, m.ColorDiffuse.G, m.ColorDiffuse.B, m.ColorDiffuse.A ); uMaterial.color = color; } // Emission if (m.HasColorEmissive) { Color color = new Color( m.ColorEmissive.R, m.ColorEmissive.G, m.ColorEmissive.B, m.ColorEmissive.A ); uMaterial.SetColor("_EmissionColor", color); uMaterial.EnableKeyword("_EMISSION"); } // Reflectivity if (m.HasReflectivity) { uMaterial.SetFloat("_Glossiness", m.Reflectivity); } // Texture if (m.HasTextureDiffuse) { Texture2D uTexture = new Texture2D(2, 2); string texturePath = Path.Combine(parentDir, m.TextureDiffuse.FilePath); byte[] byteArray = File.ReadAllBytes(texturePath); bool isLoaded = uTexture.LoadImage(byteArray); if (!isLoaded) { throw new Exception("Cannot find texture file: " + texturePath); } uMaterial.SetTexture("_MainTex", uTexture); } } uMaterials.Add(uMaterial); } } // Mesh List <MeshMaterialBinding> uMeshAndMats = new List <MeshMaterialBinding>(); if (scene.HasMeshes) { foreach (var m in scene.Meshes) { List <Vector3> uVertices = new List <Vector3>(); List <Vector3> uNormals = new List <Vector3>(); List <Vector2> uUv = new List <Vector2>(); List <int> uIndices = new List <int>(); // Vertices if (m.HasVertices) { foreach (var v in m.Vertices) { uVertices.Add(new Vector3(-v.X, v.Y, v.Z)); } } // Normals if (m.HasNormals) { foreach (var n in m.Normals) { uNormals.Add(new Vector3(-n.X, n.Y, n.Z)); } } // Triangles if (m.HasFaces) { foreach (var f in m.Faces) { // Ignore non-triangle faces if (f.IndexCount != 3) { continue; } uIndices.Add(f.Indices[2]); uIndices.Add(f.Indices[1]); uIndices.Add(f.Indices[0]); } } // Uv (texture coordinate) if (m.HasTextureCoords(0)) { foreach (var uv in m.TextureCoordinateChannels[0]) { uUv.Add(new Vector2(uv.X, uv.Y)); } } UnityEngine.Mesh uMesh = new UnityEngine.Mesh(); uMesh.vertices = uVertices.ToArray(); uMesh.normals = uNormals.ToArray(); uMesh.triangles = uIndices.ToArray(); uMesh.uv = uUv.ToArray(); uMeshAndMats.Add(new MeshMaterialBinding(m.Name, uMesh, uMaterials[m.MaterialIndex])); } } // Create GameObjects from nodes GameObject NodeToGameObject(Node node) { GameObject uOb = new GameObject(node.Name); // Set Mesh if (node.HasMeshes) { foreach (var mIdx in node.MeshIndices) { var uMeshAndMat = uMeshAndMats[mIdx]; GameObject uSubOb = new GameObject(uMeshAndMat.MeshName); MeshFilter filter = uSubOb.AddComponent <MeshFilter>(); MeshRenderer rend = uSubOb.AddComponent <MeshRenderer>(); uSubOb.AddComponent <MeshCollider>(); filter.mesh = uMeshAndMat.Mesh; rend.material = uMeshAndMat.Material; rend.receiveShadows = false; uSubOb.transform.SetParent(uOb.transform, true); uSubOb.transform.localScale = new Vector3(scaleX, scaleY, scaleZ); } } // Transform // Decompose Assimp transform into scale, rot and translaction Assimp.Vector3D aScale = new Assimp.Vector3D(); Assimp.Quaternion aQuat = new Assimp.Quaternion(); Assimp.Vector3D aTranslation = new Assimp.Vector3D(); node.Transform.Decompose(out aScale, out aQuat, out aTranslation); // Convert Assimp transfrom into Unity transform and set transformation of game object UnityEngine.Quaternion uQuat = new UnityEngine.Quaternion(aQuat.X, aQuat.Y, aQuat.Z, aQuat.W); var euler = uQuat.eulerAngles; uOb.transform.localScale = new UnityEngine.Vector3(aScale.X, aScale.Y, aScale.Z); uOb.transform.localPosition = new UnityEngine.Vector3(aTranslation.X, aTranslation.Y, aTranslation.Z); uOb.transform.localRotation = UnityEngine.Quaternion.Euler(euler.x, -euler.y, euler.z); if (node.HasChildren) { foreach (var cn in node.Children) { var uObChild = NodeToGameObject(cn); uObChild.transform.SetParent(uOb.transform, false); } } return(uOb); } Import import = new Import(scene, NodeToGameObject(scene.RootNode), null, null); if (fromLibrary == true) { import.filter = import.GO.GetComponentInChildren <MeshFilter>(); import.rend = import.GO.GetComponentInChildren <MeshRenderer>(); import.GO = import.filter.gameObject; GameObject root = import.GO.transform.root.gameObject; import.GO.transform.SetParent(null); Destroy(root); } return(import); }
public void CreateIconObject(Transform transform = null, Mesh mesh = null, Material[] materials = null) { if (iconRoot == null) { return; } if (transform != null) { iconRoot.transform.position = transform.position; iconRoot.transform.rotation = transform.rotation; iconRoot.transform.localScale = Vector3.one; } else { iconRoot.transform.position = Vector3.zero; iconRoot.transform.rotation = Quaternion.identity; iconRoot.transform.localScale = Vector3.one; } { const string IconModelName = "IconModel"; var iconModelTransform = iconRoot.transform.Find(IconModelName); if (iconModelTransform != null) { iconModel = iconModelTransform.gameObject; } if (iconModel == null) { #if PreviewObjectHide iconModel = UnityEditor.EditorUtility.CreateGameObjectWithHideFlags(IconModelName, HideFlags.HideAndDontSave); #else iconModel = new GameObject(IconModelName); iconModel.hideFlags = HideFlags.DontSave; #endif } iconModel.transform.SetParent(iconRoot.transform); iconModel.transform.localPosition = new Vector3(0f, 0f, 0f); iconModel.layer = iconRoot.layer; MeshFilter meshFilter = iconModel.GetComponent <MeshFilter>(); if (meshFilter == null) { meshFilter = iconModel.AddComponent <MeshFilter>(); } meshFilter.sharedMesh = mesh; iconModelRenderer = iconModel.GetComponent <MeshRenderer>(); if (iconModelRenderer == null) { iconModelRenderer = iconModel.AddComponent <MeshRenderer>(); } if (materials != null) { iconModelRenderer.sharedMaterials = materials; } } { const string IconCameraName = "IconCamera"; var iconCameraTransform = iconRoot.transform.Find(IconCameraName); if (iconCameraTransform != null) { iconCamera = iconCameraTransform.gameObject; } if (iconCamera == null) { #if PreviewObjectHide iconCamera = UnityEditor.EditorUtility.CreateGameObjectWithHideFlags(IconCameraName, HideFlags.HideAndDontSave); #else iconCamera = new GameObject(IconCameraName); iconCamera.hideFlags = HideFlags.DontSave; #endif iconCameraCamera = iconCamera.AddComponent <Camera>(); } else { iconCameraCamera = iconCamera.GetComponent <Camera>(); } iconCamera.transform.SetParent(iconRoot.transform); iconCamera.layer = iconRoot.layer; if (mesh != null) { var rot = Quaternion.AngleAxis(180f, Vector3.up); iconCamera.transform.localRotation = rot; iconCamera.transform.localPosition = mesh.bounds.center + iconCamera.transform.worldToLocalMatrix.MultiplyVector(iconCamera.transform.forward) * mesh.bounds.size.z * 5f; } else { iconCamera.transform.localPosition = Vector3.zero; iconCamera.transform.localRotation = Quaternion.identity; } iconCameraCamera.orthographic = true; if (mesh != null) { iconCameraCamera.orthographicSize = Mathf.Max(mesh.bounds.size.x, Mathf.Max(mesh.bounds.size.y, mesh.bounds.size.z)) * 0.6f; iconCameraCamera.farClipPlane = Mathf.Max(mesh.bounds.size.x, Mathf.Max(mesh.bounds.size.y, mesh.bounds.size.z)) * 5f; } iconCameraCamera.clearFlags = CameraClearFlags.Color; iconCameraCamera.backgroundColor = new Color(0f, 0f, 0f, 0f); iconCameraCamera.cullingMask = 1 << iconRoot.layer; iconCameraCamera.targetTexture = iconTexture; } }
/** * Helper function to accept a gameobject which will transform the plane * approprietly before the slice occurs * See -> Slice(Mesh, Plane) for more info */ public static SlicedHull Slice(GameObject obj, Plane pl, TextureRegion crossRegion, Material crossMaterial) { MeshFilter filter = obj.GetComponent <MeshFilter>(); // cannot continue without a proper filter if (filter == null) { Debug.LogWarning("EzySlice::Slice -> Provided GameObject must have a MeshFilter Component."); return(null); } MeshRenderer renderer = obj.GetComponent <MeshRenderer>(); // cannot continue without a proper renderer if (renderer == null) { Debug.LogWarning("EzySlice::Slice -> Provided GameObject must have a MeshRenderer Component."); return(null); } Material[] materials = renderer.sharedMaterials; Mesh mesh = filter.sharedMesh; // cannot slice a mesh that doesn't exist if (mesh == null) { Debug.LogWarning("EzySlice::Slice -> Provided GameObject must have a Mesh that is not NULL."); return(null); } int submeshCount = mesh.subMeshCount; // to make things straightforward, exit without slicing if the materials and mesh // array don't match. This shouldn't happen anyway if (materials.Length != submeshCount) { Debug.LogWarning("EzySlice::Slice -> Provided Material array must match the length of submeshes."); return(null); } // we need to find the index of the material for the cross section. // default to the end of the array int crossIndex = materials.Length; // for cases where the sliced material is null, we will append the cross section to the end // of the submesh array, this is because the application may want to set/change the material // after slicing has occured, so we don't assume anything if (crossMaterial != null) { for (int i = 0; i < crossIndex; i++) { if (materials[i] == crossMaterial) { crossIndex = i; break; } } } return(Slice(mesh, pl, crossRegion, crossIndex)); }
private static float FragmentVolume(GameObject fragment) { if (fragment == null) { throw new System.ArgumentNullException("fragment"); } if (!IsFragmented(fragment)) { throw new System.ArgumentException("Game object is not a valid fragment"); } MeshFilter meshFilter = fragment.GetComponent <MeshFilter>(); if (meshFilter == null) { throw new System.ArgumentException("Game object does not have a mesh filter attached to it."); } if (meshFilter.mesh == null) { throw new System.ArgumentException("Game object's mesh filter does not have a mesh."); } Mesh mesh = meshFilter.mesh; Vector3[] points = mesh.vertices; int baseStartIdx = 0; int baseEndIdx = points.Length / 6; int topStartIdx = points.Length / 6; int topEndIdx = points.Length / 3; Vector3 baseCenter = Vector3.zero; for (int i = baseStartIdx; i < baseEndIdx; ++i) { baseCenter += points[i]; } baseCenter /= baseEndIdx - 1 - baseStartIdx; Vector3 topCenter = Vector3.zero; for (int i = topStartIdx; i < topEndIdx; ++i) { topCenter += points[i]; } topCenter /= topEndIdx - 1 - topStartIdx; float baseArea = 0.0f; for (int i = baseStartIdx + 1; i < baseEndIdx - 1; ++i) { baseArea += Vector3.Cross(points[baseStartIdx] - points[i], points[baseStartIdx] - points[i + 1]).magnitude; } baseArea *= 0.5f; float topArea = 0.0f; for (int i = topStartIdx + 1; i < topEndIdx - 1; ++i) { topArea += Vector3.Cross(points[topStartIdx] - points[i], points[topStartIdx] - points[i + 1]).magnitude; } topArea *= 0.5f; float thickness = (topCenter - baseCenter).magnitude; float bigDistance = (points[baseStartIdx] - baseCenter).magnitude; float smallDistance = (points[topStartIdx] - topCenter).magnitude; float remainingThickness = thickness / (bigDistance - smallDistance); return(baseArea * (thickness + remainingThickness) / 3.0f - topArea * remainingThickness / 3.0f); }
public static bool IntersectRayMesh(Ray ray, MeshFilter meshFilter, out RaycastHit hit) { return(IntersectRayMesh(ray, meshFilter.mesh, meshFilter.transform.localToWorldMatrix, out hit)); }
public static string RecordVisibleRenderers() { Camera cam = Camera.main; if (cam == null) { return("Can't find main camera"); } VisibleRecord record = new VisibleRecord(); record.fps = 1f / Time.deltaTime; record.batches = RuntimeStats.batches; record.setPassCalls = RuntimeStats.setPassCalls; record.tris = RuntimeStats.triangles; record.verts = RuntimeStats.vertices; record.camPos = cam.transform.position; record.camDir = cam.transform.forward; record.camUp = cam.transform.up; record.camFov = cam.fieldOfView; record.camNear = cam.nearClipPlane; record.camFar = cam.farClipPlane; record.camOc = cam.useOcclusionCulling ? 1 : 0; record.camHdr = cam.allowHDR ? 1 : 0; record.camMsaa = cam.allowMSAA ? 1 : 0; record.renders = new List <string>(); var mrs = FindObjectsOfType <MeshRenderer>(); foreach (MeshRenderer mr in mrs) { if (mr != null && mr.isVisible) { string path = mr.name; Transform parentTr = mr.transform.parent; while (parentTr != null) { path = parentTr.name + "/" + path; parentTr = parentTr.parent; } path = mr.gameObject.scene.name + "/" + path; int vert = 0, tris = 0; MeshFilter mf = mr.GetComponent <MeshFilter>(); if (mf != null && mf.sharedMesh != null) { vert = mf.sharedMesh.vertexCount; tris = mf.sharedMesh.triangles.Length; } Vector3 pos = mr.transform.position; path += string.Format("=>vert:{0},tris:{1},pos:{2}", vert, tris, pos); record.renders.Add(path); } } string json = JsonUtility.ToJson(record); var now = System.DateTime.Now; System.IO.File.WriteAllText(string.Format("visible-{0}-{1}-{2}-{3}.json", now.Month, now.Day, now.Hour, now.Minute), json); return("OK"); }
} //circleOnTex public static GameObject MakePlane(float width, float length, int widthSegments, int lengthSegments, Color color, Vector3 anchorOffset, bool addCollider = false, string optionalName = "", Shader shader = null) { GameObject plane = new GameObject(); if (shader == null) { shader = Shader.Find("Diffuse"); } if (!string.IsNullOrEmpty(optionalName)) { plane.name = optionalName; } else { plane.name = "Plane"; } plane.transform.position = Vector3.zero; MeshFilter meshFilter = (MeshFilter)plane.AddComponent(typeof(MeshFilter)); MeshRenderer mr = plane.AddComponent <MeshRenderer>(); mr.material.shader = shader; mr.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; mr.receiveShadows = false; mr.reflectionProbeUsage = UnityEngine.Rendering.ReflectionProbeUsage.Off; mr.useLightProbes = false; if (color.a == 1) { mr.material.color = color; } string planeAssetName = plane.name + widthSegments + "x" + lengthSegments + "W" + width + "L" + length + ".asset"; plane.name = planeAssetName; Mesh m = new Mesh(); m.name = plane.name; int hCount2 = widthSegments + 1; int vCount2 = lengthSegments + 1; int numTriangles = widthSegments * lengthSegments * 6; int numVertices = hCount2 * vCount2; Vector3[] vertices = new Vector3[numVertices]; Vector2[] uvs = new Vector2[numVertices]; int[] triangles = new int[numTriangles]; int index = 0; float uvFactorX = 1.0f / widthSegments; float uvFactorY = 1.0f / lengthSegments; float scaleX = width / widthSegments; float scaleY = length / lengthSegments; for (float y = 0.0f; y < vCount2; y++) { for (float x = 0.0f; x < hCount2; x++) { vertices[index] = new Vector3(x * scaleX - width / 2f - anchorOffset.x, y * scaleY - length / 2f - anchorOffset.y, 0.0f); uvs[index++] = new Vector2(x * uvFactorX, y * uvFactorY); } } index = 0; for (int y = 0; y < lengthSegments; y++) { for (int x = 0; x < widthSegments; x++) { triangles[index] = (y * hCount2) + x; triangles[index + 1] = ((y + 1) * hCount2) + x; triangles[index + 2] = (y * hCount2) + x + 1; triangles[index + 3] = ((y + 1) * hCount2) + x; triangles[index + 4] = ((y + 1) * hCount2) + x + 1; triangles[index + 5] = (y * hCount2) + x + 1; index += 6; } } m.vertices = vertices; m.uv = uvs; m.triangles = triangles; m.RecalculateNormals(); meshFilter.sharedMesh = m; m.RecalculateBounds(); if (addCollider) { plane.AddComponent(typeof(BoxCollider)); } return(plane); //Selection.activeObject = plane; } //MakePlane
private void buildSphere(float radius, int longitudeSegments, int latitudeSegments) { MeshFilter filter = gameObject.AddComponent <MeshFilter>(); Mesh mesh = filter.mesh; mesh.Clear(); #region Vertices Vector3[] vertices = new Vector3[(longitudeSegments + 1) * latitudeSegments + 2]; float _pi = Mathf.PI; float _2pi = _pi * 2f; vertices[0] = Vector3.up * radius; for (int lat = 0; lat < latitudeSegments; lat++) { float a1 = _pi * (float)(lat + 1) / (latitudeSegments + 1); float sin1 = Mathf.Sin(a1); float cos1 = Mathf.Cos(a1); for (int lon = 0; lon <= longitudeSegments; lon++) { float a2 = _2pi * (float)(lon == longitudeSegments ? 0 : lon) / longitudeSegments; float sin2 = Mathf.Sin(a2); float cos2 = Mathf.Cos(a2); vertices[lon + lat * (longitudeSegments + 1) + 1] = new Vector3(sin1 * cos2, cos1, sin1 * sin2) * radius; } } vertices[vertices.Length - 1] = Vector3.up * -radius; #endregion #region Normales Vector3[] normales = new Vector3[vertices.Length]; for (int n = 0; n < vertices.Length; n++) { normales[n] = vertices[n].normalized; } #endregion #region UVs Vector2[] uvs = new Vector2[vertices.Length]; uvs[0] = Vector2.up; uvs[uvs.Length - 1] = Vector2.zero; for (int lat = 0; lat < latitudeSegments; lat++) { for (int lon = 0; lon <= longitudeSegments; lon++) { uvs[lon + lat * (longitudeSegments + 1) + 1] = new Vector2((float)lon / longitudeSegments, 1f - (float)(lat + 1) / (latitudeSegments + 1)); } } #endregion #region Triangles int nbFaces = vertices.Length; int nbTriangles = nbFaces * 2; int nbIndexes = nbTriangles * 3; int[] triangles = new int[nbIndexes]; //Top Cap int i = 0; for (int lon = 0; lon < longitudeSegments; lon++) { triangles[i++] = lon + 2; triangles[i++] = lon + 1; triangles[i++] = 0; } //Middle for (int lat = 0; lat < latitudeSegments - 1; lat++) { for (int lon = 0; lon < longitudeSegments; lon++) { int current = lon + lat * (longitudeSegments + 1) + 1; int next = current + longitudeSegments + 1; triangles[i++] = current; triangles[i++] = current + 1; triangles[i++] = next + 1; triangles[i++] = current; triangles[i++] = next + 1; triangles[i++] = next; } } //Bottom Cap for (int lon = 0; lon < longitudeSegments; lon++) { triangles[i++] = vertices.Length - 1; triangles[i++] = vertices.Length - (lon + 2) - 1; triangles[i++] = vertices.Length - (lon + 1) - 1; } #endregion mesh.vertices = vertices; mesh.normals = normales; mesh.uv = uvs; mesh.triangles = triangles; mesh.RecalculateBounds(); mesh.Optimize(); }
public static void Create(GameObject gameObject, float height, CelestialBody celestialBody) { float radius = 1; if (celestialBody == null) { radius = height; } MeshFilter filter = gameObject.AddComponent <MeshFilter>(); Mesh mesh = filter.mesh; mesh.Clear(); List <Vector3> vertList = new List <Vector3>(); Dictionary <long, int> middlePointIndexCache = new Dictionary <long, int>(); int recursionLevel = 4; if (celestialBody != null) { recursionLevel = 6; } // create 12 vertices of a icosahedron float t = (1f + Mathf.Sqrt(5f)) / 2f; vertList.Add(new Vector3(-1f, t, 0f).normalized *radius); vertList.Add(new Vector3(1f, t, 0f).normalized *radius); vertList.Add(new Vector3(-1f, -t, 0f).normalized *radius); vertList.Add(new Vector3(1f, -t, 0f).normalized *radius); vertList.Add(new Vector3(0f, -1f, t).normalized *radius); vertList.Add(new Vector3(0f, 1f, t).normalized *radius); vertList.Add(new Vector3(0f, -1f, -t).normalized *radius); vertList.Add(new Vector3(0f, 1f, -t).normalized *radius); vertList.Add(new Vector3(t, 0f, -1f).normalized *radius); vertList.Add(new Vector3(t, 0f, 1f).normalized *radius); vertList.Add(new Vector3(-t, 0f, -1f).normalized *radius); vertList.Add(new Vector3(-t, 0f, 1f).normalized *radius); // create 20 triangles of the icosahedron List <TriangleIndices> faces = new List <TriangleIndices>(); // 5 faces around point 0 faces.Add(new TriangleIndices(0, 11, 5)); faces.Add(new TriangleIndices(0, 5, 1)); faces.Add(new TriangleIndices(0, 1, 7)); faces.Add(new TriangleIndices(0, 7, 10)); faces.Add(new TriangleIndices(0, 10, 11)); // 5 adjacent faces faces.Add(new TriangleIndices(1, 5, 9)); faces.Add(new TriangleIndices(5, 11, 4)); faces.Add(new TriangleIndices(11, 10, 2)); faces.Add(new TriangleIndices(10, 7, 6)); faces.Add(new TriangleIndices(7, 1, 8)); // 5 faces around point 3 faces.Add(new TriangleIndices(3, 9, 4)); faces.Add(new TriangleIndices(3, 4, 2)); faces.Add(new TriangleIndices(3, 2, 6)); faces.Add(new TriangleIndices(3, 6, 8)); faces.Add(new TriangleIndices(3, 8, 9)); // 5 adjacent faces faces.Add(new TriangleIndices(4, 9, 5)); faces.Add(new TriangleIndices(2, 4, 11)); faces.Add(new TriangleIndices(6, 2, 10)); faces.Add(new TriangleIndices(8, 6, 7)); faces.Add(new TriangleIndices(9, 8, 1)); // refine triangles for (int i = 0; i < recursionLevel; i++) { List <TriangleIndices> faces2 = new List <TriangleIndices>(); foreach (var tri in faces) { // replace triangle by 4 triangles int a = getMiddlePoint(tri.v1, tri.v2, ref vertList, ref middlePointIndexCache, radius); int b = getMiddlePoint(tri.v2, tri.v3, ref vertList, ref middlePointIndexCache, radius); int c = getMiddlePoint(tri.v3, tri.v1, ref vertList, ref middlePointIndexCache, radius); faces2.Add(new TriangleIndices(tri.v1, a, c)); faces2.Add(new TriangleIndices(tri.v2, b, a)); faces2.Add(new TriangleIndices(tri.v3, c, b)); faces2.Add(new TriangleIndices(a, b, c)); } faces = faces2; } Vector3[] normals = new Vector3[vertList.Count]; for (int i = 0; i < normals.Length; i++) { normals[i] = vertList[i].normalized; } if (celestialBody != null) { for (int i = 0; i < vertList.Count; i++) { Vector3d rotVert = Tools.RotateY(vertList[i], .5 * Math.PI); float value = (float)(height + celestialBody.pqsController.GetSurfaceHeight(rotVert)); vertList[i] *= value; } } mesh.vertices = vertList.ToArray(); List <int> triList = new List <int>(); for (int i = 0; i < faces.Count; i++) { triList.Add(faces[i].v1); triList.Add(faces[i].v2); triList.Add(faces[i].v3); } mesh.triangles = triList.ToArray(); float invPi2 = 1 / (2 * Mathf.PI); float invPi = 1 / (Mathf.PI); List <Vector2> uvList = new List <Vector2>(); for (int i = 0; i < vertList.Count; i++) { Vector2 uv = new Vector2(); Vector3 normal = vertList[i].normalized; uv.x = 0.5f + invPi2 * Mathf.Atan2(normal.z, normal.x); uv.y = 0.5f - invPi * Mathf.Asin(normal.y); uvList.Add(uv); } mesh.uv = uvList.ToArray(); mesh.normals = normals; Tools.CalculateMeshTangents(mesh); mesh.RecalculateBounds(); mesh.Optimize(); }
// Functions //----------------------------------------------------------------- // 1. Init private void ChildMeshesToMaskedMesh() { this.enabled = false; _isVisible = false; if (_renderer == null) { _renderer = gameObject.AddComponent <MeshRenderer>(); _material = new Material(Shader.Find("AnyPortrait/Transparent/Masked Colored Texture (2X)")); _material.name = "AnyPortrait Material (Instance)"; _material.color = new Color(0.5f, 0.5f, 0.5f, 0.5f); _renderer.material = _material; } if (_meshFilter == null) { _meshFilter = gameObject.AddComponent <MeshFilter>(); _mesh = new Mesh(); _meshFilter.mesh = _mesh; } for (int i = 0; i < _subMeshes.Length; i++) { _subMeshes[i] = null; } _vertices = null; _triangles = null; _uvs = null; _vertColors = null; if (_childMesh_Base == null) { return; //이게 없으면 끝입니더 } _subMeshes[SUBMESH_BASE] = new SubMeshMap(SUBMESH_BASE, _childMesh_Base); if (_childMesh_Clip1 != null) { _subMeshes[SUBMESH_CLIP1] = new SubMeshMap(SUBMESH_CLIP1, _childMesh_Clip1); } if (_childMesh_Clip2 != null) { _subMeshes[SUBMESH_CLIP2] = new SubMeshMap(SUBMESH_CLIP2, _childMesh_Clip2); } if (_childMesh_Clip3 != null) { _subMeshes[SUBMESH_CLIP3] = new SubMeshMap(SUBMESH_CLIP3, _childMesh_Clip3); } //이제 Vertex List를 만들어주자 List <Vector3> vertList = new List <Vector3>(); List <int> triList = new List <int>(); List <Vector2> uvList = new List <Vector2>(); List <Color> vertColorList = new List <Color>(); int curVertexIndexOffset = 0; for (int i = 0; i < _subMeshes.Length; i++) { if (_subMeshes[i] == null) { continue; } Transform subTransform = _subMeshes[i]._transform; _subMeshes[i].SetVertexIndexOffset(curVertexIndexOffset); Vector3[] subVerts = _subMeshes[i]._vertices; int[] subTris = _subMeshes[i]._triangles; Vector2[] subUVs = _subMeshes[i]._uvs; Color vertColor = Color.clear; switch (i) { case SUBMESH_BASE: vertColor = VertexColor_Base; break; case SUBMESH_CLIP1: vertColor = VertexColor_Clip1; break; case SUBMESH_CLIP2: vertColor = VertexColor_Clip2; break; case SUBMESH_CLIP3: vertColor = VertexColor_Clip3; break; } for (int iVert = 0; iVert < subVerts.Length; iVert++) { vertList.Add(transform.InverseTransformPoint(subTransform.TransformPoint(subVerts[iVert]))); vertColorList.Add(vertColor); } for (int iTri = 0; iTri < subTris.Length; iTri++) { triList.Add(subTris[iTri] + curVertexIndexOffset); } for (int iUV = 0; iUV < subUVs.Length; iUV++) { uvList.Add(subUVs[iUV]); } //다음을 위해 Offset 추가 curVertexIndexOffset += subVerts.Length; //Sub Mesh는 안보이게 하자 _subMeshes[i]._renderer.enabled = false; } //만든 리스트를 Vertex 배열로 바꾸기 _vertices = vertList.ToArray(); _triangles = triList.ToArray(); _uvs = uvList.ToArray(); _vertColors = vertColorList.ToArray(); //메시에 넣자 _mesh.Clear(); _mesh.vertices = _vertices; _mesh.triangles = _triangles; _mesh.uv = _uvs; _mesh.colors = _vertColors; _mesh.RecalculateNormals(); _mesh.RecalculateBounds(); //재질에도 넣자 Color color_Base = new Color(0.5f, 0.5f, 0.5f, 1.0f); Color color_Clip1 = new Color(0.0f, 0.0f, 0.0f, 0.0f); Color color_Clip2 = new Color(0.0f, 0.0f, 0.0f, 0.0f); Color color_Clip3 = new Color(0.0f, 0.0f, 0.0f, 0.0f); Texture texture_Base = null; Texture texture_Clip1 = null; Texture texture_Clip2 = null; Texture texture_Clip3 = null; if (_subMeshes[SUBMESH_BASE] != null) { color_Base = _subMeshes[SUBMESH_BASE]._color; texture_Base = _subMeshes[SUBMESH_BASE]._texture; } if (_subMeshes[SUBMESH_CLIP1] != null) { color_Clip1 = _subMeshes[SUBMESH_CLIP1]._color; texture_Clip1 = _subMeshes[SUBMESH_CLIP1]._texture; } if (_subMeshes[SUBMESH_CLIP2] != null) { color_Clip2 = _subMeshes[SUBMESH_CLIP2]._color; texture_Clip2 = _subMeshes[SUBMESH_CLIP2]._texture; } if (_subMeshes[SUBMESH_CLIP3] != null) { color_Clip3 = _subMeshes[SUBMESH_CLIP3]._color; texture_Clip3 = _subMeshes[SUBMESH_CLIP3]._texture; } _material.SetColor("_Color", color_Base); _material.SetColor("_Color1", color_Clip1); _material.SetColor("_Color2", color_Clip2); _material.SetColor("_Color3", color_Clip3); _material.SetTexture("_MainTex", texture_Base); _material.SetTexture("_ClipTexture1", texture_Clip1); _material.SetTexture("_ClipTexture2", texture_Clip2); _material.SetTexture("_ClipTexture3", texture_Clip3); _isVisible = false; Show(); }
static void CombineMesh() { Transform targetTf = Selection.activeGameObject.transform; if (!EditorUtility.DisplayDialog("确认", "确定要合并网格吗?", "确定", "取消")) { return; } MeshFilter targetMF = targetTf.GetComponent <MeshFilter>(); //按材质球分组 Dictionary <Material, List <MFNode> > dicMatMF = new Dictionary <Material, List <MFNode> >(); MeshFilter[] meshFilters = targetTf.GetComponentsInChildren <MeshFilter>(false); for (int i = 0; i < meshFilters.Length; i++) { MeshFilter mfT = meshFilters[i]; if (mfT.transform == targetTf) { continue; } Material matT = meshFilters[i].GetComponent <MeshRenderer>().sharedMaterial; if (!dicMatMF.ContainsKey(matT)) { List <MFNode> listMFNode = new List <MFNode>(); AddAMFToMFNode(mfT, listMFNode); dicMatMF.Add(matT, listMFNode); } else { AddAMFToMFNode(mfT, dicMatMF[matT]); } } foreach (Material mat in dicMatMF.Keys) { int nodeIndex = 0; foreach (MFNode mfNode in dicMatMF[mat]) { nodeIndex++; List <MeshFilter> listMf = mfNode.mfs; //开始合并 CombineInstance[] combine = new CombineInstance[listMf.Count]; for (int i = 0; i < listMf.Count; i++) { combine[i].mesh = listMf[i].sharedMesh; combine[i].transform = listMf[i].transform.localToWorldMatrix; listMf[i].gameObject.SetActive(false); } string assetName = targetTf.name + "_" + mat.name + nodeIndex; GameObject gobjNew = new GameObject(assetName); gobjNew.transform.parent = targetTf; gobjNew.transform.position = Vector3.zero; MeshFilter mf = gobjNew.AddComponent <MeshFilter>(); MeshRenderer mr = gobjNew.AddComponent <MeshRenderer>(); mf.mesh = new Mesh(); mf.sharedMesh.CombineMeshes(combine, true);//为mesh.CombineMeshes添加一个 false 参数,表示并不是合并为一个网格,而是一个子网格列表 mr.sharedMaterial = mat; //创建网格资源 string path = "/CombineMeshExport"; if (!Directory.Exists(Application.dataPath + path)) { Directory.CreateDirectory(Application.dataPath + path); } AssetDatabase.CreateAsset(mf.sharedMesh, string.Format("{0}/{1}.asset", "Assets" + path, assetName)); } } }
/// <summary> /// The main initialisation. Here we create the subcomponents. /// </summary> void Awake() { if (!GetComponent<ParticleEmitter>()) { emitter = gameObject.AddComponent<MeshParticleEmitter>(); emitter.useWorldSpace = false; emitter.emit = true; } else { emitter = GetComponent<ParticleEmitter>(); } if (!GetComponent<ParticleAnimator>()) { animator = gameObject.AddComponent<ParticleAnimator>(); animator.doesAnimateColor = true; } else { animator = GetComponent<ParticleAnimator>(); } if (!GetComponent<ParticleRenderer>()) { renderer = gameObject.AddComponent<ParticleRenderer>(); renderer.material = new Material(Shader.Find("Particles/Alpha Blended")); } else { renderer = GetComponent<ParticleRenderer>(); } filter = !GetComponent<MeshFilter>() ? gameObject.AddComponent<MeshFilter>() : GetComponent<MeshFilter>(); }
private static string MeshToString(MeshFilter mf, Dictionary <string, ObjMaterial> materialList) { Mesh m = mf.sharedMesh; Material[] mats = mf.GetComponent <Renderer>().sharedMaterials; StringBuilder sb = new StringBuilder(); sb.Append("g ").Append(mf.name).Append("\n"); foreach (Vector3 lv in m.vertices) { Vector3 wv = mf.transform.TransformPoint(lv); //This is sort of ugly - inverting x-component since we're in //a different coordinate system than "everyone" is "used to". sb.Append(string.Format("v {0} {1} {2}\n", -wv.x, wv.y, wv.z)); } sb.Append("\n"); foreach (Vector3 lv in m.normals) { Vector3 wv = mf.transform.TransformDirection(lv); sb.Append(string.Format("vn {0} {1} {2}\n", -wv.x, wv.y, wv.z)); } sb.Append("\n"); foreach (Vector3 v in m.uv) { sb.Append(string.Format("vt {0} {1}\n", v.x, v.y)); } for (int material = 0; material < m.subMeshCount; material++) { sb.Append("\n"); sb.Append("usemtl ").Append(mats[material].name).Append("\n"); sb.Append("usemap ").Append(mats[material].name).Append("\n"); //See if this material is already in the materiallist. try { ObjMaterial objMaterial = new ObjMaterial(); objMaterial.name = mats[material].name; if (mats[material].mainTexture) { objMaterial.textureName = AssetDatabase.GetAssetPath(mats[material].mainTexture); } else { objMaterial.textureName = null; } materialList.Add(objMaterial.name, objMaterial); } catch (ArgumentException) { //Already in the dictionary } int[] triangles = m.GetTriangles(material); for (int i = 0; i < triangles.Length; i += 3) { //Because we inverted the x-component, we also needed to alter the triangle winding. sb.Append(string.Format("f {1}/{1}/{1} {0}/{0}/{0} {2}/{2}/{2}\n", triangles[i] + 1 + vertexOffset, triangles[i + 1] + 1 + normalOffset, triangles[i + 2] + 1 + uvOffset)); } } vertexOffset += m.vertices.Length; normalOffset += m.normals.Length; uvOffset += m.uv.Length; return(sb.ToString()); }
public void Init(Factory factory) { renderers = new List<IMeshRenderer>(); mesh = new Mesh(); mesh.name = "LWF/" + factory.data.name; mesh.MarkDynamic(); meshFilter = gameObject.AddComponent<MeshFilter>(); meshFilter.sharedMesh = mesh; meshRenderer = gameObject.AddComponent<UnityEngine.MeshRenderer>(); #if UNITY_4_6 meshRenderer.castShadows = false; #else meshRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; #endif meshRenderer.receiveShadows = false; UpdateSortingLayerAndOrder(factory); UpdateLayer(factory); if (factory.useAdditionalColor) { additionalColor = UnityEngine.Color.clear; property = new MaterialPropertyBlock(); additionalColorId = Shader.PropertyToID("_AdditionalColor"); } buffer = new CombinedMeshBuffer(); }
/// <summary> /// Gets only the current transform's bounds. /// </summary> /// <param name="transform">The transform of the object</param> /// <param name="space">An option to return the bounds based on local or world space</param> /// <param name="useCollider">Uses the collider instead of the renderer to calculate the bounds of the object</param> /// <param name="applyScale">Multiplies the bounds size by the transform's local scale</param> /// <returns>A bounds that encapsulates only the given transform's model</returns> public static Bounds GetBounds(this Transform transform, Space space, bool useCollider = false, bool applyScale = false) { Bounds singleBounds = default; if (useCollider) { Collider collider = transform.GetComponent <Collider>(); if (collider != null) { var localBounds = collider.GetLocalBounds(); if (space == Space.World) { localBounds = transform.TransformBounds(localBounds); } else if (applyScale) { localBounds = new Bounds(localBounds.center, localBounds.size.Multiply(transform.localScale)); } singleBounds = localBounds; } else { var collider2D = transform.GetComponent <Collider2D>(); if (collider2D != null) { var localBounds = collider2D.GetLocalBounds(); if (space == Space.World) { localBounds = transform.TransformBounds(localBounds); } else if (applyScale) { localBounds = new Bounds(localBounds.center, localBounds.size.Multiply(transform.localScale)); } singleBounds = localBounds; } } } else { Renderer renderer = transform.GetComponent <Renderer>(); if (renderer != null) { if (space == Space.World) { singleBounds = renderer.bounds; } else { if (renderer is SpriteRenderer) { singleBounds = ((SpriteRenderer)renderer).sprite.bounds; } else if (renderer is SkinnedMeshRenderer) { singleBounds = ((SkinnedMeshRenderer)renderer).localBounds; } else { MeshFilter meshFilter = transform.GetComponent <MeshFilter>(); if (meshFilter != null) { singleBounds = meshFilter.sharedMesh.bounds; } } if (applyScale) { singleBounds = new Bounds(singleBounds.center, singleBounds.size.Multiply(transform.localScale)); } } } } return(singleBounds); }
public Factory(Data d, GameObject gObj, float zOff = 0, float zR = 1, int rQOff = 0, bool uAC = false, Camera cam = null, string texturePrfx = "", string fontPrfx = "", TextureLoader textureLdr = null, TextureUnloader textureUnldr = null) : base(gObj, zOff, zR, rQOff, uAC, cam, texturePrfx, fontPrfx, textureLdr, textureUnldr) { data = d; mesh = new Mesh(); mesh.name = "LWF/" + data.name; #if !UNITY_3_5 mesh.MarkDynamic(); #endif if (Application.isEditor) { meshFilter = gameObject.GetComponent<MeshFilter>(); if (meshFilter == null) meshFilter = gameObject.AddComponent<MeshFilter>(); } else { meshFilter = gameObject.AddComponent<MeshFilter>(); } meshFilter.sharedMesh = mesh; if (Application.isEditor) { meshRenderer = gameObject.GetComponent<UnityEngine.MeshRenderer>(); if (meshRenderer == null) meshRenderer = gameObject.AddComponent<UnityEngine.MeshRenderer>(); } else { meshRenderer = gameObject.AddComponent<UnityEngine.MeshRenderer>(); } meshRenderer.castShadows = false; meshRenderer.receiveShadows = false; textureName = texturePrefix + data.textures[0].filename; meshRenderer.sharedMaterial = ResourceCache.SharedInstance().LoadTexture( data.name, textureName, data.textures[0].format, true, useAdditionalColor, textureLoader, textureUnloader); if (renderQueueOffset != 0) meshRenderer.sharedMaterial.renderQueue += renderQueueOffset; premultipliedAlpha = (data.textures[0].format == (int)Format.Constant.TEXTUREFORMAT_PREMULTIPLIEDALPHA); buffer = new CombinedMeshBuffer(); CreateBitmapContexts(data); }
public void initialize() { m_MeshFilter = GetComponent<MeshFilter>(); m_MeshRenderer = GetComponent<MeshRenderer>(); }