public void CombineMeshes(CombineInstance[] combine, bool mergeSubMeshes){}
public void Combine() { if (!forceDuplicateCombine && transform.Find("Combined mesh") != null) { completed = true; return; } if (DEBUG) { //print("START called on: " + gameObject.name + "in hex: " + transform.parent.gameObject.name); StartCoroutine(wait()); } completed = false; Matrix4x4 myTransform = transform.worldToLocalMatrix; Dictionary <Material, List <CombineInstance> > combines = new Dictionary <Material, List <CombineInstance> >(); MeshRenderer[] meshRenderers = GetComponentsInChildren <MeshRenderer>(); foreach (var meshRenderer in meshRenderers) { foreach (var material in meshRenderer.sharedMaterials) { if (material != null && !combines.ContainsKey(material)) { combines.Add(material, new List <CombineInstance>()); } } } MeshFilter[] meshFilters = GetComponentsInChildren <MeshFilter>(); //if(DEBUG) print("Number of filters: " + meshFilters.Length); foreach (var filter in meshFilters) { if (filter.sharedMesh == null) { continue; } CombineInstance ci = new CombineInstance(); ci.mesh = filter.sharedMesh; ci.transform = myTransform * filter.transform.localToWorldMatrix; combines[filter.GetComponent <Renderer>().sharedMaterial].Add(ci); if (DEBUG) { filter.GetComponent <Renderer>().enabled = true; } else { filter.GetComponent <Renderer>().enabled = false; } } int counter = 0; //if(DEBUG) print("Number of materials: " + combines.Keys.Count); foreach (Material m in combines.Keys) { if (counter < 3) { var go = new GameObject("Combined mesh"); // + counter); go.transform.parent = transform; go.transform.localPosition = Vector3.zero; go.transform.localRotation = Quaternion.identity; go.transform.localScale = Vector3.one; var filter = go.AddComponent <MeshFilter>(); filter.mesh.CombineMeshes(combines[m].ToArray(), true, true); var renderer = go.AddComponent <MeshRenderer>(); renderer.material = m; } if (DEBUG) { counter++; } } completed = true; }
void Start() { //stage情報初期化 stage = variables.stage; //法線初期化 normalVector = new Vector3[variables.trapezoidDivisionNum + 1, 6]; normalBasicVec = new Vector3[variables.trapezoidDivisionNum + 1, 6]; if (myParent == null) { createSorce = GameObject.Find("central").GetComponent <createTrapezoidPole>(); //現在のTextSetの段数を取得 poleSum = variables.poleSum; } else { createSorce = myParent.GetComponent <createTrapezoidPole>(); //自分の親の名前から該当TextSetの行からアイテム数を取得 //Debug.Log(myParent.name.Substring(9)); poleSum = GameObject.Find("central").GetComponent <centralSystem>().GetTextSetItemNum(int.Parse(myParent.name.Substring(9))); } systemScript = GameObject.Find("central").GetComponent <centralSystem>(); //自分の番号を名前から取得し初期化 poleNum = int.Parse(transform.name) - 1; //LineVertex初期化 最初の面4頂点+中間面4頂点+最後の面4頂点 LineVertex = new Vector3[4 + variables.trapezoidDivisionNum * 4 + 4]; //格納先も初期化 lineVertecies = new Vector3[8 + 4 * variables.trapezoidDivisionNum + 8]; // CombineMeshes()する時に使う配列 始端と終端も含めるので+3 CombineInstance[] combineInstanceAry = new CombineInstance[variables.trapezoidDivisionNum + 3]; //メッシュ作成 for (DivisionNum = 0; DivisionNum <= variables.trapezoidDivisionNum; DivisionNum++) { //頂点計算 CalcVertices(); if (DivisionNum == 0) { //最初の一枚だけ別計算 //メッシュ作成 Mesh meshFirst = new Mesh(); //メッシュリセット meshFirst.Clear(); //メッシュへの頂点情報の追加 meshFirst.vertices = StartVertex; //メッシュへの面情報の追加 meshFirst.triangles = EndFace; // 合成するMesh(同じMeshを円形に並べたMesh) combineInstanceAry[0].mesh = meshFirst; combineInstanceAry[0].transform = Matrix4x4.Translate(transform.position); } Mesh mesh = new Mesh(); //メッシュリセット mesh.Clear(); //メッシュへの頂点情報の追加 mesh.vertices = SideVertex; //メッシュへの面情報の追加 mesh.triangles = SideFace; //合成するMesh(同じMeshを円形に並べたMesh) combineInstanceAry[DivisionNum + 1].mesh = mesh; combineInstanceAry[DivisionNum + 1].transform = Matrix4x4.Translate(transform.position); if (DivisionNum == variables.trapezoidDivisionNum) { //最後の一枚だけ別計算 //メッシュ作成 Mesh meshLast = new Mesh(); //メッシュリセット meshLast.Clear(); //メッシュへの頂点情報の追加 meshLast.vertices = EndVertex; //メッシュへの面情報の追加 meshLast.triangles = EndFace; // 合成するMesh(同じMeshを円形に並べたMesh) combineInstanceAry[DivisionNum + 2].mesh = meshLast; combineInstanceAry[DivisionNum + 2].transform = Matrix4x4.Translate(transform.position); } } //合成した(する)メッシュ Mesh combinedMesh = new Mesh(); combinedMesh.name = transform.name; combinedMesh.CombineMeshes(combineInstanceAry); //内向き法線の計算 culcNormal(combinedMesh.vertices); //メッシュフィルター追加 MeshFilter mesh_filter = new MeshFilter(); mesh_filter = this.gameObject.AddComponent <MeshFilter>(); //メッシュアタッチ mesh_filter.mesh = combinedMesh; //レンダラー追加 + マテリアルアタッチ meshRenderer = this.gameObject.AddComponent <MeshRenderer>(); meshRenderer.material = variables.material_TrapezoidPole_Normal; //コライダーアタッチ meshCollider = this.gameObject.AddComponent <MeshCollider>(); meshCollider.sharedMesh = mesh_filter.mesh; meshCollider.convex = true; meshCollider.isTrigger = true; //NormalMapの再計算 mesh_filter.mesh.RecalculateNormals(); //XRじゃないなら if (!variables.isOnXR) { //暫定当たり判定用Event Trigger //イベントトリガーのアタッチと初期化 EventTrigger currentTrigger = this.gameObject.AddComponent <EventTrigger>(); currentTrigger.triggers = new List <EventTrigger.Entry>(); //侵入イベント用 //侵入時に色を変える //イベントトリガーのトリガーイベント作成 EventTrigger.Entry entry1 = new EventTrigger.Entry(); entry1.eventID = EventTriggerType.PointerEnter; entry1.callback.AddListener((x) => OnMouseEnterOwnMade()); //ラムダ式の右側は追加するメソッド //トリガーイベントのアタッチ currentTrigger.triggers.Add(entry1); //侵入終了時に色を戻す EventTrigger.Entry entry2 = new EventTrigger.Entry(); entry2.eventID = EventTriggerType.PointerExit; entry2.callback.AddListener((x) => OnMouseExitOwnMade()); currentTrigger.triggers.Add(entry2); } //テキスト表示 make3Dtext(); //縁取り lineRenderer = this.gameObject.AddComponent <LineRenderer>(); //ローカルで描画 lineRenderer.useWorldSpace = false; //頂点数 lineRenderer.positionCount = lineVertecies.Length; //幅 lineRenderer.startWidth = variables.lineRendererWidth; //順番の格納 SetLineVertecies(); lineRenderer.SetPositions(lineVertecies); //線の折れる部分の丸み具合 lineRenderer.numCornerVertices = 20; //線の端の丸み具合 lineRenderer.numCapVertices = 20; //線の色 lineRenderer.material = variables.material_LineRenderer; //影を発生させない lineRenderer.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; //影の影響を受けない lineRenderer.receiveShadows = false; //クリエイト元を親にする transform.parent = createSorce.gameObject.transform; }
public Mesh GenerateMesh() { List <CombineInstance> cisOpaque = new List <CombineInstance>(); List <CombineInstance> cisTransparent = new List <CombineInstance>(); List <IBlock> blocks = new List <IBlock>(blocksInChunk.Values); for (int i = 0; i < blocks.Count; i++) { CombineInstance ci = new CombineInstance { mesh = blocks[i].GetMesh(), transform = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, Vector3.one) }; if (blocks[i] is ITransparentBlock) { cisTransparent.Add(ci); } else { cisOpaque.Add(ci); } } /* * Mesh meshOpaque = new Mesh(); * meshOpaque.CombineMeshes(cisOpaque.ToArray()); * Mesh meshTransparent = new Mesh(); * meshOpaque.CombineMeshes(cisTransparent.ToArray()); * * Mesh finalMesh = new Mesh(); * CombineInstance[] cis = new CombineInstance[] { * new CombineInstance() { mesh = meshOpaque }, * new CombineInstance() { mesh = meshTransparent } * }; */ Mesh opaqueMesh = new Mesh(); Mesh transparentMesh = new Mesh(); opaqueMesh.CombineMeshes(cisOpaque.ToArray()); transparentMesh.CombineMeshes(cisTransparent.ToArray()); Mesh finalMesh = new Mesh(); CombineInstance[] cis = new CombineInstance[] { new CombineInstance() { mesh = opaqueMesh, transform = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, Vector3.one) }, new CombineInstance() { mesh = transparentMesh, transform = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, Vector3.one) }, }; finalMesh.CombineMeshes(cis, false); if (finalMesh.subMeshCount == 1) { finalMesh.subMeshCount = 2; } return(finalMesh); }
public override List <Model> Modify(List <Model> input) { List <Model> output = new List <Model>(); /*if (spline) { * if (fit == Fit.Spline && updateOnSpline) spline.OnRefresh.AddListenerOnce(OnSplineRefreshEvent); * else spline.OnRefresh.RemoveListener(OnSplineRefreshEvent); * }*/ //int count = GetCount(inputMesh); //Loop through input models for (int i = 0; i < input.Count; i++) { CombineInstance[] finalCombines = new CombineInstance[input[i].mesh.subMeshCount]; //Loop through model submeshes for (int g = 0; g < input[i].mesh.subMeshCount; g++) { //Create a CombineInstance array for the submesh CombineInstance[] submeshCombines = new CombineInstance[count]; //Perform the array modifier for (int k = 0; k < count; k++) { Vector3 pos = posOffset * k; Vector3 rot = rotOffset * k; Vector3 scale = Vector3.one; /*if (fit != Fit.Count && scaleToFit) { * float segmentWidth = GetSegmentWidth(inputMesh); //eg 4 * float lengthToFit = GetLength(); //eg 11.12041 * float fitScale = lengthToFit / (segmentWidth * count); //eg 1.390052 * Vector3 fitAxis = posOffset / segmentWidth; //eg (0,0,1) * Vector3 fitScaleOffset = fitAxis * fitScale; //eg (0,0,1.390052) * * scale.x *= Mathf.Lerp(1f, fitScaleOffset.x, fitAxis.x); * scale.y *= Mathf.Lerp(1f, fitScaleOffset.y, fitAxis.y); * scale.z *= Mathf.Lerp(1f, fitScaleOffset.z, fitAxis.z); * pos.x *= Mathf.Lerp(1f, fitScaleOffset.x, fitAxis.x); * pos.y *= Mathf.Lerp(1f, fitScaleOffset.y, fitAxis.y); * pos.z *= Mathf.Lerp(1f, fitScaleOffset.z, fitAxis.z); * * }*/ //scale += (scaleOffset * k); //Setup CombineInstance submeshCombines[k] = new CombineInstance() { mesh = input[i].mesh, transform = Matrix4x4.TRS(pos, Quaternion.Euler(rot), scale), subMeshIndex = g }; } Mesh arrayedSubmesh = new Mesh(); arrayedSubmesh.CombineMeshes(submeshCombines, true); finalCombines[g] = new CombineInstance() { mesh = arrayedSubmesh, transform = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, Vector3.one), }; } Mesh finalMesh = new Mesh(); finalMesh.CombineMeshes(finalCombines, false); output.Add(new Model(finalMesh, input[i].materials)); } return(output); }
public IEnumerator GenerateHLOD(bool propagateUpwards = true) { var mergeChildrenVolumes = false; HashSet <Renderer> hlodRenderers = new HashSet <Renderer>(); var rendererMaterials = renderers.SelectMany(r => r.sharedMaterials); yield return(null); foreach (Transform child in transform) { var childLODVolume = child.GetComponent <LODVolume>(); if (childLODVolume && childLODVolume.renderers.Count > 0) { if (rendererMaterials.Except(childLODVolume.renderers.SelectMany(r => r.sharedMaterials)).Any()) { hlodRenderers.Clear(); mergeChildrenVolumes = false; break; } var childHLODRoot = childLODVolume.hlodRoot; if (childHLODRoot) { var childHLODRenderer = childHLODRoot.GetComponent <Renderer>(); if (childHLODRenderer) { mergeChildrenVolumes = true; hlodRenderers.Add(childHLODRenderer); continue; } } hlodRenderers.Clear(); mergeChildrenVolumes = false; break; } yield return(null); } if (!mergeChildrenVolumes) { foreach (var r in renderers) { var mr = r as MeshRenderer; if (mr) { // Use the coarsest LOD if it exists var mrLODGroup = mr.GetComponentInParent <LODGroup>(); if (mrLODGroup) { var mrLODs = mrLODGroup.GetLODs(); var maxLOD = mrLODGroup.GetMaxLOD(); var mrLOD = mrLODs[maxLOD]; foreach (var lr in mrLOD.renderers) { if (lr && lr.GetComponent <MeshFilter>()) { hlodRenderers.Add(lr); } } } else if (mr.GetComponent <MeshFilter>()) { hlodRenderers.Add(mr); } } yield return(null); } } var lodRenderers = new List <Renderer>(); CleanupHLOD(); GameObject hlodRootContainer = null; yield return(ObjectUtils.FindGameObject(k_HLODRootContainer, root => { if (root) { hlodRootContainer = root; } })); if (!hlodRootContainer) { hlodRootContainer = new GameObject(k_HLODRootContainer); } var hlodLayer = LayerMask.NameToLayer(HLODLayer); hlodRoot = new GameObject("HLOD"); hlodRoot.layer = hlodLayer; hlodRoot.transform.parent = hlodRootContainer.transform; if (mergeChildrenVolumes) { Material sharedMaterial = null; CombineInstance[] combine = new CombineInstance[hlodRenderers.Count]; var i = 0; foreach (var r in hlodRenderers) { var mf = r.GetComponent <MeshFilter>(); var ci = new CombineInstance(); ci.transform = r.transform.localToWorldMatrix; ci.mesh = mf.sharedMesh; combine[i] = ci; if (sharedMaterial == null) { sharedMaterial = r.sharedMaterial; } i++; } var sharedMesh = new Mesh(); #if UNITY_2017_3_OR_NEWER sharedMesh.indexFormat = IndexFormat.UInt32; #endif sharedMesh.CombineMeshes(combine, true, true); sharedMesh.RecalculateBounds(); var meshFilter = hlodRoot.AddComponent <MeshFilter>(); meshFilter.sharedMesh = sharedMesh; var meshRenderer = hlodRoot.AddComponent <MeshRenderer>(); meshRenderer.sharedMaterial = sharedMaterial; } else { var parent = hlodRoot.transform; foreach (var r in hlodRenderers) { var rendererTransform = r.transform; var child = new GameObject(r.name, typeof(MeshFilter), typeof(MeshRenderer)); child.layer = hlodLayer; var childTransform = child.transform; childTransform.SetPositionAndRotation(rendererTransform.position, rendererTransform.rotation); childTransform.localScale = rendererTransform.lossyScale; childTransform.SetParent(parent, true); var mr = child.GetComponent <MeshRenderer>(); EditorUtility.CopySerialized(r.GetComponent <MeshFilter>(), child.GetComponent <MeshFilter>()); EditorUtility.CopySerialized(r.GetComponent <MeshRenderer>(), mr); lodRenderers.Add(mr); } } LOD lod = new LOD(); var lodGroup = GetComponent <LODGroup>(); if (!lodGroup) { lodGroup = gameObject.AddComponent <LODGroup>(); } this.lodGroup.lodGroup = lodGroup; if (!mergeChildrenVolumes) { var batcher = (IBatcher)Activator.CreateInstance(batcherType); yield return(batcher.Batch(hlodRoot)); } lod.renderers = hlodRoot.GetComponentsInChildren <Renderer>(false); lodGroup.SetLODs(new LOD[] { lod }); if (propagateUpwards) { var lodVolumeParent = transform.parent; var parentLODVolume = lodVolumeParent ? lodVolumeParent.GetComponentInParent <LODVolume>() : null; if (parentLODVolume) { yield return(parentLODVolume.GenerateHLOD()); } } }
// Merge meshes together for faster drawing. public void MergeMeshes() { if (AreMeshesMerged) { return; } // First make a list of all top-level child meshes that don't // have animators attached. Dictionary <Material, List <MeshRenderer> > staticMeshes = new Dictionary <Material, List <MeshRenderer> >(); mergedMeshHolder = new GameObject(); mergedMeshHolder.name = "MergedMeshHolder"; foreach (GameObject obj in sceneObjects.Values) { foreach (Transform child in obj.transform) { bool hasAnimator = child.GetComponentsInChildren <Animator>().Length > 0; if (!hasAnimator) { foreach (MeshRenderer meshRenderer in child.GetComponentsInChildren <MeshRenderer>()) { if (meshRenderer.enabled) { int materialHash = meshRenderer.sharedMaterial.GetHashCode(); if (!staticMeshes.ContainsKey(meshRenderer.sharedMaterial)) { staticMeshes.Add(meshRenderer.sharedMaterial, new List <MeshRenderer>()); } staticMeshes[meshRenderer.sharedMaterial].Add(meshRenderer); Destroy(meshRenderer); } } } } } foreach (Material mat in staticMeshes.Keys) { List <MeshRenderer> meshList = staticMeshes[mat]; CombineInstance[] combineArray = new CombineInstance[meshList.Count]; int i = 0; foreach (MeshRenderer meshRenderer in meshList) { MeshFilter meshFilter = meshRenderer.gameObject.GetComponent <MeshFilter>(); if (meshFilter != null) { combineArray[i].mesh = meshFilter.mesh; combineArray[i].transform = meshFilter.transform.localToWorldMatrix; i++; } } GameObject meshHolder = new GameObject(); meshHolder.name = "MeshHolder"; meshHolder.transform.SetParent(mergedMeshHolder.transform, false); MeshRenderer newRenderer = meshHolder.AddComponent <MeshRenderer>(); MeshFilter newFilter = meshHolder.AddComponent <MeshFilter>(); newFilter.mesh = new Mesh(); newFilter.mesh.CombineMeshes(combineArray, true); newRenderer.material = mat; } }
public void CollectMesh(Armature armature, List <CombineMeshInfo> combineSlots) { if (armature == null) { return; } var slots = new List <Slot>(armature.GetSlots()); if (slots.Count == 0) { return; } // var isBreakCombineMesh = false; var isSameMaterial = false; var isChildAramture = false; UnitySlot slotMeshProxy = null; GameObject slotDisplay = null; for (var i = 0; i < slots.Count; i++) { var slot = slots[i] as UnitySlot; slot.CancelCombineMesh(); isChildAramture = slot.childArmature != null; slotDisplay = slot.renderDisplay; if (slotMeshProxy != null) { if (slot._meshBuffer.name == string.Empty) { isSameMaterial = true; } else { isSameMaterial = slotMeshProxy._meshBuffer.name == slot._meshBuffer.name; } } else { isSameMaterial = slotMeshProxy == null; } //先检查这个slot会不会打断网格合并 isBreakCombineMesh = isChildAramture || slot._isIgnoreCombineMesh || slot._blendMode != BlendMode.Normal || !isSameMaterial; //如果会打断,那么先合并一次 if (isBreakCombineMesh) { if (combineSlots.Count > 0) { if (combineSlots[combineSlots.Count - 1].combines.Count == 1) { combineSlots.RemoveAt(combineSlots.Count - 1); } } slotMeshProxy = null; } // if (slotMeshProxy == null && !isBreakCombineMesh && slotDisplay != null && slotDisplay.activeSelf) { CombineMeshInfo combineSlot = new CombineMeshInfo(); combineSlot.proxySlot = slot; combineSlot.combines = new List <CombineInstance>(); combineSlot.slots = new List <UnitySlot>(); combineSlots.Add(combineSlot); slotMeshProxy = slot; } //如果不会合并,检查一下是否是子骨架 if (isChildAramture) { continue; } if (slotMeshProxy != null && slotDisplay != null && slotDisplay.activeSelf && !slot._isIgnoreCombineMesh) { var parentTransfrom = (slot._armature.proxy as UnityArmatureComponent).transform; CombineInstance com = new CombineInstance(); com.mesh = slot._meshBuffer.sharedMesh; com.transform = slotMeshProxy._renderDisplay.transform.worldToLocalMatrix * slotDisplay.transform.localToWorldMatrix; combineSlots[combineSlots.Count - 1].combines.Add(com); combineSlots[combineSlots.Count - 1].slots.Add(slot); } if (i != slots.Count - 1) { continue; } // if (combineSlots.Count > 0) { if (combineSlots[combineSlots.Count - 1].combines.Count == 1) { combineSlots.RemoveAt(combineSlots.Count - 1); } } slotMeshProxy = null; } }
private void PreprocessInputMesh() { if (deformedMesh == null) { deformedMesh = new Mesh(); deformedMesh.name = "deformedMesh"; deformedMesh.MarkDynamic(); GetComponent <MeshFilter>().mesh = deformedMesh; } deformedMesh.Clear(); if (mesh == null) { orderedVertices = new int[0]; return; } // Clamp instance count to a positive value. instances = Mathf.Max(0, instances); // combine all mesh instances into a single mesh: Mesh combinedMesh = new Mesh(); CombineInstance[] meshInstances = new CombineInstance[instances]; Vector3 pos = Vector3.zero; // initial offset for the combined mesh is half the size of its bounding box in the swept axis: pos[(int)axis] = mesh.bounds.extents[(int)axis]; for (int i = 0; i < instances; ++i) { meshInstances[i].mesh = mesh; meshInstances[i].transform = Matrix4x4.TRS(pos, Quaternion.identity, Vector3.one); pos[(int)axis] = mesh.bounds.extents[(int)axis] + (i + 1) * mesh.bounds.size[(int)axis] * instanceSpacing; } combinedMesh.CombineMeshes(meshInstances, true, true); // get combined mesh data: inputVertices = combinedMesh.vertices; inputNormals = combinedMesh.normals; inputTangents = combinedMesh.tangents; // sort vertices along curve axis: float[] keys = new float[inputVertices.Length]; orderedVertices = new int[inputVertices.Length]; for (int i = 0; i < keys.Length; ++i) { keys[i] = inputVertices[i][(int)axis]; orderedVertices[i] = i; } Array.Sort(keys, orderedVertices); // Copy the combined mesh data to deform it: deformedMesh.vertices = combinedMesh.vertices; deformedMesh.normals = combinedMesh.normals; deformedMesh.tangents = combinedMesh.tangents; deformedMesh.uv = combinedMesh.uv; deformedMesh.uv2 = combinedMesh.uv2; deformedMesh.uv3 = combinedMesh.uv3; deformedMesh.uv4 = combinedMesh.uv4; deformedMesh.colors = combinedMesh.colors; deformedMesh.triangles = combinedMesh.triangles; vertices = deformedMesh.vertices; normals = deformedMesh.normals; tangents = deformedMesh.tangents; // Calculate scale along swept axis so that the mesh spans the entire lenght of the rope if required. meshSizeAlongAxis = combinedMesh.bounds.size[(int)axis]; // destroy combined mesh: GameObject.DestroyImmediate(combinedMesh); }
public void Generate() { float startTime = Time.realtimeSinceStartup; #region Create Mesh Data List <CombineInstance> blockData = new List <CombineInstance>(); //this will contain the data for the final mesh MeshFilter blockMesh = Instantiate(blockPrefab, Vector3.zero, Quaternion.identity).GetComponentInChildren <MeshFilter>(); //create a unit cube and store the mesh from it //go through each block position for (int x = 0; x < chunkSize; x++) { for (int y = 0; y < chunkSize; y++) { for (int z = 0; z < chunkSize; z++) { float noiseValue = Perlin3D(x * noiseScale, y * noiseScale, z * noiseScale, seed); //get value of the noise at given x, y, and z. if (noiseValue >= threshold) { //is noise value above the threshold for placing a block? //ignore this block if it's a sphere and it's outside of the radius (ex: in the corner of the chunk, outside of the sphere) //distance between the current point with the center point. if it's larger than the radius, then it's not inside the sphere. float radius = chunkSize / 2; if (sphere && Vector3.Distance(new Vector3(x, y, z), Vector3.one * radius) > radius) { continue; } if (cube && Vector3.Distance(new Vector3(x, y, z), Vector3.one * radius) < radius * 0.6f) { continue; } if (rhombus && Vector3.Distance(new Vector3(x, y, z), Vector3.one * radius) > radius * 0.8f && Vector3.Distance(new Vector3(x, y, z), Vector3.one * radius) < radius) { continue; } blockMesh.transform.position = new Vector3(x, y, z); //move the unit cube to the intended position CombineInstance ci = new CombineInstance { //copy the data off of the unit cube mesh = blockMesh.sharedMesh, transform = blockMesh.transform.localToWorldMatrix, }; blockData.Add(ci);//add the data to the list } } } } Destroy(blockMesh.gameObject);//original unit cube is no longer needed. we copied all the data we need to the block list. #endregion #region Separate Mesh Data //divide meshes into groups of 65536 vertices. Meshes can only have 65536 vertices so we need to divide them up into multiple block lists. List <List <CombineInstance> > blockDataLists = new List <List <CombineInstance> >(); //we will store the meshes in a list of lists. each sub-list will contain the data for one mesh. same data as blockData, different format. int vertexCount = 0; blockDataLists.Add(new List <CombineInstance>()); //initial list of mesh data for (int i = 0; i < blockData.Count; i++) { //go through each element in the previous list and add it to the new list. vertexCount += blockData[i].mesh.vertexCount; //keep track of total vertices if (vertexCount > 65536) { //if the list has reached it's capacity. if total vertex count is more then 65536, reset counter and start adding them to a new list. vertexCount = 0; blockDataLists.Add(new List <CombineInstance>()); i--; } else { //if the list hasn't yet reached it's capacity. safe to add another block data to this list blockDataLists.Last().Add(blockData[i]); //the newest list will always be the last one added } } #endregion #region Create Mesh //the creation of the final mesh from the data. Transform container = new GameObject("Meshys").transform;//create container object container.transform.position = new Vector3(Random.Range(0, 1024), Random.Range(50, 500), Random.Range(0, 1024)); foreach (List <CombineInstance> data in blockDataLists) { //for each list (of block data) in the list (of other lists) GameObject g = new GameObject("Meshy"); //create gameobject for the mesh g.transform.parent = container; //set parent to the container we just made MeshFilter mf = g.AddComponent <MeshFilter>(); //add mesh component MeshRenderer mr = g.AddComponent <MeshRenderer>(); //add mesh renderer component MeshCollider mc = g.AddComponent <MeshCollider>(); //add mesh collider component mr.material = material; //set material to avoid evil pinkness of missing texture mf.mesh.CombineMeshes(data.ToArray()); //set mesh to the combination of all of the blocks in the list mc.sharedMesh = mf.mesh; //derive colllider from the combined mesh meshes.Add(mf.mesh); //keep track of mesh so we can destroy it when it's no longer needed //g.AddComponent<MeshCollider>().sharedMesh = mf.sharedMesh;//setting colliders takes more time. disabled for testing. meshObjects.Add(g); } PositionOnTerrain(); #endregion Debug.Log("Loaded in " + (Time.realtimeSinceStartup - startTime) + " Seconds."); }
/// <summary> /// Primary recursive function used to grow segments of the body, and attached stems /// </summary> /// <param name="firstSegment">special modifier for the 'head' or first segment of the body</param> /// <param name="number">number of segments to grow, counts down to 0</param> /// <param name="meshes">reference to list of combine instances</param> /// <param name="pos">where to spawn the segment</param> /// <param name="rot">rotation of the segment</param> /// <param name="bodyScale">how much to scale each segment</param> /// <param name="switchDirection">used to change direction the segment grows in</param> /// <param name="stems">reference to list of combine instances for stems and leaves</param> void GrowBody(bool firstSegment, int number, List <CombineInstance> meshes, Vector3 pos, Quaternion rot, float bodyScale, bool switchDirection, List <CombineInstance> stems) { if (number <= 0) { return; } CombineInstance inst = new CombineInstance(); inst.mesh = MeshTools.MakeCylinder(5); inst.transform = Matrix4x4.TRS(pos, rot, new Vector3(bodyWidth, bodyScale, bodyWidth) * scale); meshes.Add(inst); //scale //rotation ; Vector3 stemRotation = new Vector3(); //calculate which way to grow the next segment if (switchDirection) {//top side rot = Quaternion.Euler(-90, 0, 0); if (!firstSegment) { stemRotation.Set(-45, 0, 0); } } else {//bottom side rot = Quaternion.Euler(-180, 0, 0); if (!firstSegment) { stemRotation.Set(135, 0, 0); } } //don't spawn stems from the first segment if (!firstSegment) { //random chance for 2 stems if (Random.Range(0, 100) < chanceForMoreStems) { stemRotation = new Vector3(stemRotation.x, stemRotation.y, -45); GrowStem(stemSize, stems, pos, Quaternion.Euler(stemRotation), switchDirection); stemRotation = new Vector3(stemRotation.x, stemRotation.y, 45); } GrowStem(stemSize, stems, pos, Quaternion.Euler(stemRotation), switchDirection); } switchDirection = !switchDirection; pos = inst.transform.MultiplyPoint(new Vector3(0, 1, 0)); //de increment iterations number--; //grow another segment GrowBody(false, number, meshes, pos, rot, bodyScale, switchDirection, stems); }
// FIXME: This most of this method is horrendously unoptimized, optimize it later // Combines meshes with differing materials into a parent mesh subdivided into submeshes public void MultiMaterialCombine() { // Caches frequently used references and components CacheReferences(); // The output mesh where all other final submeshes are combined Mesh outputMesh = new Mesh(); // Creates a new list to store the materials List <Material> materials = new List <Material>(); // Creates an array of submeshes. Each submesh will contain a material Mesh[] subMeshes; // Creates a list of sublists of combine instances for each material // FIXME: Doing this is horrendous for performance List <List <CombineInstance> > combineInstanceLists = new List <List <CombineInstance> >(); // HACK: To avoid annoying matrix math, we instead are resetting the position and restoring it later Quaternion rotation = transform.rotation; Vector3 position = transform.position; // For each of the children mesh filters foreach (MeshFilter meshFilter in childrenMeshFilters) { // Gets the mesh renderer attached to the mesh filter MeshRenderer meshRenderer = meshFilter.GetComponent <MeshRenderer>(); // Skips if it is the container if (meshFilter == containerMeshFilter) { continue; } // Skips if the mesh renderer is null or the meshfilter's shared mesh is null or the mesh renderer's material count is different from the mesh filter's submesh count // This is important because each submesh is a material; therefore, if there are more materials than submeshes, the mesh combine will fail if (!meshRenderer || !meshFilter.sharedMesh || meshRenderer.sharedMaterials.Length != meshFilter.sharedMesh.subMeshCount) { continue; } // For each submesh in the meshfilter's mesh for (int sharedMaterialIndex = 0; sharedMaterialIndex < meshFilter.sharedMesh.subMeshCount; sharedMaterialIndex++) { // If the material does not exist in the materials list if (!materials.Contains(meshRenderer.sharedMaterials[sharedMaterialIndex])) { // Add the material to the materials list materials.Add(meshRenderer.sharedMaterials[sharedMaterialIndex]); } // Instantiates the material sublist combineInstanceLists.Add(new List <CombineInstance>()); // Creates a new combine instance to store data about the mesh CombineInstance combineInstance = new CombineInstance(); // Populates combineInstance with data combineInstance.transform = meshRenderer.transform.localToWorldMatrix; combineInstance.subMeshIndex = sharedMaterialIndex; combineInstance.mesh = meshFilter.sharedMesh; // Adds the combine instance to the material sublist combineInstanceLists[sharedMaterialIndex].Add(combineInstance); } // Disables the child's meshrenderer meshRenderer.enabled = false; } // Combine material index into a per-material mesh // Initializes the submesh array subMeshes = new Mesh[materials.Count]; // Creates a new combine instance for each material CombineInstance[] finalCombineInstances = new CombineInstance[materials.Count]; // For each material in materials for (int sharedMaterialIndex = 0; sharedMaterialIndex < materials.Count; sharedMaterialIndex++) { // Generates an array of combine instances that will be used to generate each submesh CombineInstance[] subfinalCombineInstances = combineInstanceLists[sharedMaterialIndex].ToArray(); // Assigns a new mesh to the submesh array entry subMeshes[sharedMaterialIndex] = new Mesh(); // Combines the meshes in the sub combine instances array subMeshes[sharedMaterialIndex].CombineMeshes(subfinalCombineInstances); // Assigns a new combine index to the final combine instances array finalCombineInstances[sharedMaterialIndex] = new CombineInstance(); // Gives it the combined mesh of the subcombiners finalCombineInstances[sharedMaterialIndex].mesh = subMeshes[sharedMaterialIndex]; // Set submesh index to 0, since we no longer need to worry about each submesh containing a material finalCombineInstances[sharedMaterialIndex].subMeshIndex = 0; } // Combine submeshes into output mesh // mergeSubMeshes submeshes is set to false, because we need them to display individual materials // useMatrices is set to false because we want to ignore the transform of the submeshes outputMesh.CombineMeshes(finalCombineInstances, false, false); // Sets the container's mesh to the output mesh containerMeshFilter.sharedMesh = outputMesh; containerMeshFilter.sharedMesh.name = "Combined mesh"; // Assigns materials to container mesh renderer containerRenderer.sharedMaterials = materials.ToArray(); // Warns the developer the combined mesh exceeds unity's vertex limit if (outputMesh.vertexCount >= 65535) { Debug.LogError("The combined mesh exceeds Unity's limit of 65,535 vertices per mesh! Try combining fewer meshes!"); Debug.Log("Automatically uncombined meshes."); Uncombine(); } // Resets rotation and position transform.rotation = Quaternion.identity; transform.position = transform.position; // Marks meshes as combined meshesAreCombined = true; }
public void CombineFromNet() { SkinnedMeshRenderer[] smRenderers = GetComponentsInChildren <SkinnedMeshRenderer>(); List <Transform> bones = new List <Transform>(); List <BoneWeight> boneWeights = new List <BoneWeight>(); List <CombineInstance> combineInstances = new List <CombineInstance>(); List <Texture2D> textures = new List <Texture2D>(); int numSubs = 0; foreach (SkinnedMeshRenderer smr in smRenderers) { numSubs += smr.sharedMesh.subMeshCount; } int[] meshIndex = new int[numSubs]; int boneOffset = 0; for (int s = 0; s < smRenderers.Length; s++) { SkinnedMeshRenderer smr = smRenderers[s]; BoneWeight[] meshBoneweight = smr.sharedMesh.boneWeights; // May want to modify this if the renderer shares bones as unnecessary bones will get added. foreach (BoneWeight bw in meshBoneweight) { BoneWeight bWeight = bw; bWeight.boneIndex0 += boneOffset; bWeight.boneIndex1 += boneOffset; bWeight.boneIndex2 += boneOffset; bWeight.boneIndex3 += boneOffset; boneWeights.Add(bWeight); } boneOffset += smr.bones.Length; Transform[] meshBones = smr.bones; foreach (Transform bone in meshBones) { bones.Add(bone); } if (smr.material.mainTexture != null) { textures.Add(smr.GetComponent <Renderer>().material.mainTexture as Texture2D); } CombineInstance ci = new CombineInstance(); ci.mesh = smr.sharedMesh; meshIndex[s] = ci.mesh.vertexCount; ci.transform = smr.transform.localToWorldMatrix; combineInstances.Add(ci); Object.Destroy(smr.gameObject); } List <Matrix4x4> bindposes = new List <Matrix4x4>(); for (int b = 0; b < bones.Count; b++) { bindposes.Add(bones[b].worldToLocalMatrix * transform.worldToLocalMatrix); } SkinnedMeshRenderer r = gameObject.AddComponent <SkinnedMeshRenderer>(); r.sharedMesh = new Mesh(); r.sharedMesh.CombineMeshes(combineInstances.ToArray(), true, true); Texture2D skinnedMeshAtlas = new Texture2D(128, 128); Rect[] packingResult = skinnedMeshAtlas.PackTextures(textures.ToArray(), 0); Vector2[] originalUVs = r.sharedMesh.uv; Vector2[] atlasUVs = new Vector2[originalUVs.Length]; int rectIndex = 0; int vertTracker = 0; for (int i = 0; i < atlasUVs.Length; i++) { atlasUVs[i].x = Mathf.Lerp(packingResult[rectIndex].xMin, packingResult[rectIndex].xMax, originalUVs[i].x); atlasUVs[i].y = Mathf.Lerp(packingResult[rectIndex].yMin, packingResult[rectIndex].yMax, originalUVs[i].y); if (i >= meshIndex[rectIndex] + vertTracker) { vertTracker += meshIndex[rectIndex]; rectIndex++; } } Material combinedMat = new Material(Shader.Find("Diffuse")); combinedMat.mainTexture = skinnedMeshAtlas; r.sharedMesh.uv = atlasUVs; r.sharedMaterial = combinedMat; r.bones = bones.ToArray(); r.sharedMesh.boneWeights = boneWeights.ToArray(); r.sharedMesh.bindposes = bindposes.ToArray(); r.sharedMesh.RecalculateBounds(); }
private void RedrawRenderer(MeshVisualizeInfo mvi) { GameObject g; renderers.TryGetValue(mvi, out g); if (g != null) { int n = blockVisualizersList.Count; if (n > 0) { var indexes = new List <int>(); for (int i = 0; i < n; i++) { if (blockVisualizersList[i].meshInfo == mvi) { indexes.Add(i); } } n = indexes.Count; if (n > 0) { CombineInstance[] cir = new CombineInstance[n], cic = new CombineInstance[n]; BlockpartVisualizeInfo bvi; Mesh cm; Matrix4x4 mtr; for (int i = 0; i < n; i++) { bvi = blockVisualizersList[indexes[i]]; cm = MeshMaster.GetMesh(bvi.meshType, bvi.materialID); cir[i].mesh = cm; mtr = bvi.GetPositionMatrix(); cir[i].transform = mtr; cic[i].mesh = bvi.meshType == MeshType.Quad ? cm : MeshMaster.GetMeshColliderLink(bvi.meshType); cic[i].transform = mtr; } cm = new Mesh(); cm.CombineMeshes(cir); g.GetComponent <MeshFilter>().sharedMesh = cm; cm = new Mesh(); cm.CombineMeshes(cic); g.GetComponent <MeshCollider>().sharedMesh = cm; if (PoolMaster.useIlluminationSystem) { g.GetComponent <MeshRenderer>().sharedMaterial = PoolMaster.GetMaterial(mvi.materialType, mvi.illumination); } else { g.GetComponent <MeshRenderer>().sharedMaterial = PoolMaster.GetMaterial(mvi.materialType); } } else { renderers.Remove(mvi); Destroy(g); } } } else { CreateBlockpartsRenderer(mvi); } }
private void CreateBlockpartsRenderer(MeshVisualizeInfo mvi) { if (renderers.ContainsKey(mvi)) { return; } var processingIndexes = new List <int>(); for (int i = 0; i < blockVisualizersList.Count; i++) { if (blockVisualizersList[i].meshInfo == mvi) { processingIndexes.Add(i); } } int pcount = processingIndexes.Count; if (pcount > 0) { var ci = new CombineInstance[pcount]; Mesh m; BlockpartVisualizeInfo cdata; for (int j = 0; j < pcount; j++) { cdata = blockVisualizersList[processingIndexes[j]]; m = MeshMaster.GetMesh(cdata.meshType, cdata.materialID); ci[j].mesh = m; ci[j].transform = cdata.GetPositionMatrix(); } GameObject g = new GameObject(); m = new Mesh(); m.CombineMeshes(ci, true); // все подмеши используют один материал //удаление копий вершин на стыках - отменено из-за uv var mf = g.AddComponent <MeshFilter>(); mf.sharedMesh = m; var mr = g.AddComponent <MeshRenderer>(); mr.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; mr.receiveShadows = PoolMaster.shadowCasting; mr.lightProbeUsage = UnityEngine.Rendering.LightProbeUsage.Off; mr.reflectionProbeUsage = UnityEngine.Rendering.ReflectionProbeUsage.Off; if (!PoolMaster.useIlluminationSystem) { mr.sharedMaterial = PoolMaster.GetMaterial(mvi.materialType); } else { mr.sharedMaterial = PoolMaster.GetMaterial(mvi.materialType, mvi.illumination); } g.transform.parent = renderersHolders[mvi.faceIndex].transform; g.AddComponent <MeshCollider>().sharedMesh = m; g.tag = BLOCK_COLLIDER_TAG; renderers.Add(mvi, g); } }
private IEnumerator display(int lod) { this.manager.displayingRegions.Add(this); this.computingDisplay = true; MeshFilter filter = this.gameObject.GetComponent <MeshFilter>(); if (filter != null) { Destroy(filter.mesh); filter.mesh = null; } int pointsBuffer = 0; for (int i = 0; i < REGIONSIZE - lod; i = i + lod) { for (int j = 0; j < REGIONSIZE - lod; j = j + lod) { float[] pointHeightmap = new float[] { this.heightmap[i, j], this.heightmap[i + lod, j], this.heightmap[i, j + lod], this.heightmap[i + lod, j + lod] }; this.points[i, j].display(lod, pointHeightmap); pointsBuffer++; if (pointsBuffer >= WorldRegionManager.REGIONSPOINTSDISPLAYBUFFERSIZE) { pointsBuffer = 0; yield return(new WaitForEndOfFrame()); } } } List <MeshFilter> meshFilters = new List <MeshFilter>(); for (int i = 0; i < REGIONSIZE; i++) { for (int j = 0; j < REGIONSIZE; j++) { if (this.points[i, j].gameObject.GetComponent <MeshFilter>() != null) { meshFilters.Add(this.points[i, j].gameObject.GetComponent <MeshFilter>()); } } } CombineInstance[] combineInstances = new CombineInstance[meshFilters.Count]; for (int i = 0; i < combineInstances.Length; i++) { if (meshFilters[i] != null) { combineInstances[i].mesh = meshFilters[i].mesh; combineInstances[i].transform = Matrix4x4.TRS(this.gameObject.transform.InverseTransformPoint(meshFilters[i].gameObject.transform.position), Quaternion.Inverse(meshFilters[i].gameObject.transform.rotation), Vector3.one); } } MeshRenderer renderer = this.gameObject.GetComponent <MeshRenderer>(); if (renderer == null) { renderer = this.gameObject.AddComponent <MeshRenderer>(); } filter = this.gameObject.GetComponent <MeshFilter>(); if (filter == null) { filter = this.gameObject.AddComponent <MeshFilter>(); Mesh mesh = new Mesh(); filter.mesh = mesh; } filter.mesh.CombineMeshes(combineInstances); filter.mesh.RecalculateBounds(); filter.mesh.RecalculateNormals(); switch (this.manager.regionsType) { case WorldRegionManager.RegionsType.Sand: renderer.material = (Material)Instantiate(this.level.resources[61]); renderer.sharedMaterial = (Material)Instantiate(this.level.resources[61]); break; case WorldRegionManager.RegionsType.Rock: renderer.material = (Material)Instantiate(this.level.resources[62]); renderer.sharedMaterial = (Material)Instantiate(this.level.resources[62]); break; } for (int i = 0; i < REGIONSIZE; i++) { for (int j = 0; j < REGIONSIZE; j++) { Destroy(this.points[i, j].gameObject); this.points[i, j] = null; } } this.manager.displayingRegions.Remove(this); this.computingDisplay = false; this.status = Status.Displayed; //Debug.Log("WorldRegion " + this.ToString() + " displayed"); }
private void CombineWalls() { Vector3 basePosition = transform.position; Quaternion baseRotation = transform.rotation; transform.position = Vector3.zero; transform.rotation = Quaternion.identity; ArrayList materials = new ArrayList(); ArrayList combineInstanceArrays = new ArrayList(); MeshFilter[] meshFilters = wallMesh.GetComponentsInChildren <MeshFilter>(); //Linq solution to make sure we don't combine any of the doors(a door is easily identifiable by it's rigidbody component, so we look for that). meshFilters = meshFilters.Where((source, index) => !(source.transform.name == "FloorMesh" || source.transform.name == "WallMesh" || source.transform.GetComponent <Rigidbody>() || source.transform.GetComponentInParent <Rigidbody>())).ToArray(); foreach (MeshFilter meshFilter in meshFilters) { MeshRenderer meshRenderer = meshFilter.GetComponent <MeshRenderer>(); if (!meshRenderer || !meshFilter.sharedMesh || meshRenderer.sharedMaterials.Length != meshFilter.sharedMesh.subMeshCount) { print(meshFilter.gameObject.name); continue; } for (int s = 0; s < meshFilter.sharedMesh.subMeshCount; s++) { if (meshRenderer.sharedMaterials[s]) { int materialArrayIndex = Contains(materials, meshRenderer.sharedMaterials[s].name); if (materialArrayIndex == -1) { materials.Add(meshRenderer.sharedMaterials[s]); materialArrayIndex = materials.Count - 1; } combineInstanceArrays.Add(new ArrayList()); CombineInstance combineInstance = new CombineInstance(); combineInstance.transform = meshRenderer.transform.localToWorldMatrix; combineInstance.subMeshIndex = s; combineInstance.mesh = meshFilter.sharedMesh; (combineInstanceArrays[materialArrayIndex] as ArrayList).Add(combineInstance); } } } // Get / Create mesh filter & renderer MeshFilter meshFilterCombine = wallMesh.GetComponent <MeshFilter>(); if (meshFilterCombine == null) { meshFilterCombine = wallMesh.AddComponent <MeshFilter>(); } MeshRenderer meshRendererCombine = gameObject.GetComponent <MeshRenderer>(); if (meshRendererCombine == null) { meshRendererCombine = wallMesh.AddComponent <MeshRenderer>(); } // Combine by material index into per-material meshes // also, Create CombineInstance array for next step Mesh[] meshes = new Mesh[materials.Count]; CombineInstance[] combineInstances = new CombineInstance[materials.Count]; for (int m = 0; m < materials.Count; m++) { CombineInstance[] combineInstanceArray = (combineInstanceArrays[m] as ArrayList).ToArray(typeof(CombineInstance)) as CombineInstance[]; meshes[m] = new Mesh(); meshes[m].CombineMeshes(combineInstanceArray, true, true); combineInstances[m] = new CombineInstance(); combineInstances[m].mesh = meshes[m]; combineInstances[m].subMeshIndex = 0; } // Combine into one meshFilterCombine.sharedMesh = new Mesh(); meshFilterCombine.sharedMesh.CombineMeshes(combineInstances, false, false); // Destroy other meshes foreach (Mesh oldMesh in meshes) { oldMesh.Clear(); DestroyImmediate(oldMesh); } // Assign materials Material[] materialsArray = materials.ToArray(typeof(Material)) as Material[]; meshRendererCombine.materials = materialsArray; foreach (MeshFilter meshFilter in meshFilters) { if (!meshFilter || meshFilter.transform.GetComponent <Rigidbody>() || meshFilter.transform.GetComponentInParent <Rigidbody>() || meshFilter.transform.GetComponentInChildren <Rigidbody>()) { continue; } print(meshFilter.gameObject.transform.parent.name); DestroyImmediate(meshFilter.gameObject.transform.parent.gameObject); } wallMesh.transform.position = basePosition; wallMesh.transform.rotation = baseRotation; wallMesh.AddComponent <MeshCollider>().sharedMesh = wallMesh.GetComponent <MeshFilter>().sharedMesh; }
// GENERATE PAIR_REPEATER public override GameObject generate(bool makeGameObjects, AXParametricObject initiator_po, bool isReplica) { //Debug.Log ("PairRepeater::Generate "); if (parametricObject == null || !parametricObject.isActive) { return(null); } preGenerate(); if ((nodeSrc_p == null || nodeSrc_p.meshes == null || nodeSrc_p.meshes.Count == 0) && (nodeSrc_po != null && !(nodeSrc_po.generator is PrefabInstancer))) { return(null); } if (P_Node == null || P_Node.DependsOn == null) { return(null); } GameObject go = null; if (makeGameObjects && !parametricObject.combineMeshes) { go = ArchimatixUtils.createAXGameObject(parametricObject.Name, parametricObject); } List <AXMesh> ax_meshes = new List <AXMesh>(); GameObject plugGO = null; if (makeGameObjects && !parametricObject.combineMeshes) { plugGO = nodeSrc_po.generator.generate(true, initiator_po, isReplica); if (plugGO == null) { return(null); } } float separationX = zAxis ? 0 : separation; float separationZ = zAxis ? -separation : 0; CombineInstance[] boundsCombinator = new CombineInstance[2]; // * RIGHT INSTANCE * // -------------------------------------------------------------------- // Right Instance is at Address 0... Matrix4x4 localPlacement_mx = localNodeMatrixFromAddress(0); // use submeshes for right instance // AX_MESHES for (int mi = 0; mi < P_Node.DependsOn.meshes.Count; mi++) { AXMesh dep_amesh = P_Node.DependsOn.meshes [mi]; ax_meshes.Add(dep_amesh.Clone(localPlacement_mx * dep_amesh.transMatrix)); } // BOUNDING MESHES boundsCombinator[0].mesh = nodeSrc_po.boundsMesh; boundsCombinator[0].transform = localPlacement_mx * nodeSrc_po.generator.localMatrixWithAxisRotationAndAlignment; // GAME_OBJECTS if (plugGO != null && makeGameObjects && !parametricObject.combineMeshes) { Matrix4x4 mx = localPlacement_mx * nodeSrc_po.generator.localMatrixWithAxisRotationAndAlignment; GameObject copyGO = (GameObject)GameObject.Instantiate(plugGO, AXUtilities.GetPosition(mx), AXUtilities.QuaternionFromMatrix(mx)); copyGO.transform.localScale = nodeSrc_po.getLocalScaleAxisRotated(); AXGameObject axgo = copyGO.GetComponent <AXGameObject>(); if (axgo != null) { axgo.consumerAddress = "node_0"; } copyGO.name = copyGO.name + "_node_right"; copyGO.transform.parent = go.transform; } // * INVERSE (LEFT) INSTANCE // -------------------------------------------------------------------- // ***--- AX_MESHES - INVERSE (LEFT) ---*** translate = new Vector3(-separationX / 2, 0, -separationZ / 2); // LOCAL PLACEMENT localPlacement_mx = localNodeMatrixFromAddress(1); // use submeshes for left instance for (int mi = 0; mi < P_Node.DependsOn.meshes.Count; mi++) { // CLONE AXMesh dep_amesh = P_Node.DependsOn.meshes [mi]; AXMesh clone = dep_amesh.Clone(); // SYMETRICAL? if (symmetrical) { clone.mesh = AXMesh.freezeWithMatrix(dep_amesh.mesh, symmetryM * dep_amesh.transMatrix); clone.transMatrix = localPlacement_mx * symmetryM.inverse; } else { clone = dep_amesh.Clone(localPlacement_mx * symmetryM.inverse * dep_amesh.transMatrix); } // ADD TO AX_MESHES ax_meshes.Add(clone); } // BOUNDING MESHES boundsCombinator[1].mesh = nodeSrc_po.boundsMesh; boundsCombinator[1].transform = localPlacement_mx * nodeSrc_po.generator.localMatrixWithAxisRotationAndAlignment; // *** --- INVERSE (LEFT) - GAME_OBJECT ---** if (plugGO != null && makeGameObjects && !parametricObject.combineMeshes) { // LOCAL PLACEMENT //Matrix4x4 mx = localPlacement_mx * symmetryM * nodeSrc_po.generator.localMatrixWithAxisRotationAndAlignment; Matrix4x4 mx = localPlacement_mx * nodeSrc_po.generator.localMatrixWithAxisRotationAndAlignment; // GAME_OBJECT GameObject copyGO = (GameObject)GameObject.Instantiate(plugGO, AXUtilities.GetPosition(mx), AXUtilities.QuaternionFromMatrix(mx)); copyGO.transform.localScale = nodeSrc_po.getLocalScaleAxisRotated(); // SYMETRICAL? if (symmetrical) { copyGO.transform.localScale = copyGO.transform.localScale * -1; if (zAxis) { copyGO.transform.Rotate(0, 180, 180); } else { copyGO.transform.Rotate(180, 0, 0); } } // Force a refreshing of the colliders down the instatiatined hierachy // Based on a solution provided by pkamat here:http://forum.unity3d.com/threads/how-to-update-a-mesh-collider.32467/ foreach (MeshCollider mc in copyGO.GetComponentsInChildren <MeshCollider>()) { mc.sharedMesh = null; mc.sharedMesh = mc.gameObject.GetComponent <MeshFilter>().sharedMesh; } // ADD GAME_OBJECT AXGameObject axgo = copyGO.GetComponent <AXGameObject>(); if (axgo != null) { axgo.consumerAddress = "node_1"; } copyGO.name = copyGO.name + "_node_left"; copyGO.transform.parent = go.transform; } GameObject.DestroyImmediate(plugGO); // COMBINE ALL THE MESHES CombineInstance[] combine = new CombineInstance[ax_meshes.Count]; int combineCt = 0; for (int i = 0; i < ax_meshes.Count; i++) { AXMesh _amesh = ax_meshes [i]; combine [combineCt].mesh = _amesh.mesh; combine [combineCt].transform = _amesh.transMatrix; combineCt++; } Mesh combinedMesh = new Mesh(); combinedMesh.CombineMeshes(combine); combinedMesh.RecalculateBounds(); // BOUNDARY - Use combined meshes for boundary setBoundsWithCombinator(boundsCombinator); /* * // BOUNDS & CENTER * * Vector3 margin = new Vector3(source_po.bounds.size.x, source_po.bounds.size.y, source_po.bounds.size.z); * Bounds b = new Bounds(); * b.size = new Vector3(separationX + margin.x, margin.y, separationZ + margin.z); * b.extents = b.size/2; * b.center = source_po.bounds.center;// + new Vector3(0, b.extents.y, 0); * * parametricObject.margin = margin; * parametricObject.bounds = b; */ // FINISH parametricObject.finishMultiAXMeshAndOutput(ax_meshes, isReplica); // Turn ax_meshes into GameObjects if (makeGameObjects) { if (parametricObject.combineMeshes) { go = parametricObject.makeGameObjectsFromAXMeshes(ax_meshes, true, false); // If combine, use combined mesh as invisible collider MeshFilter mf = (MeshFilter)go.GetComponent(typeof(MeshFilter)); if (mf == null) { mf = (MeshFilter)go.AddComponent(typeof(MeshFilter)); } if (mf != null) { mf.sharedMesh = combinedMesh; parametricObject.addCollider(go); } } //Matrix4x4 tmx = parametricObject.generator.localMatrix; Matrix4x4 tmx = parametricObject.getLocalMatrix(); go.transform.rotation = AXUtilities.QuaternionFromMatrix(tmx); go.transform.position = AXUtilities.GetPosition(tmx); go.transform.localScale = parametricObject.getLocalScaleAxisRotated(); return(go); } return(null); }
void Start() { Matrix4x4 myTransform = transform.worldToLocalMatrix; combines = new Dictionary <string, List <CombineInstance> >(); namedMaterials = new Dictionary <string, Material>(); //For each mesh renderer within all children attached to this gameobject MeshRenderer[] meshRenderers = GetComponentsInChildren <MeshRenderer>(); foreach (var meshRenderer in meshRenderers) { //Grab each material in shared materials for the current mesh renderer foreach (var material in meshRenderer.sharedMaterials) { if (material != null && !combines.ContainsKey(material.name)) { combines.Add(material.name, new List <CombineInstance>()); namedMaterials.Add(material.name, material); } } } MeshFilter[] meshFilters = GetComponentsInChildren <MeshFilter>(); foreach (var filter in meshFilters) { if (filter.sharedMesh == null) { continue; } var filterRenderer = filter.GetComponent <Renderer>(); if (filterRenderer.sharedMaterial == null) { continue; } if (filterRenderer.sharedMaterials.Length > 1) { continue; } CombineInstance ci = new CombineInstance { mesh = filter.sharedMesh, transform = myTransform * filter.transform.localToWorldMatrix }; combines[filterRenderer.sharedMaterial.name].Add(ci); Destroy(filterRenderer); } foreach (Material m in namedMaterials.Values) { var go = new GameObject("Combined mesh"); go.transform.parent = transform; go.transform.localPosition = Vector3.zero; go.transform.localRotation = Quaternion.identity; go.transform.localScale = Vector3.one; var filter = go.AddComponent <MeshFilter>(); filter.mesh.CombineMeshes(combines[m.name].ToArray(), true, true); var arenderer = go.AddComponent <MeshRenderer>(); arenderer.material = m; } turnOnLightsAfterMeshCombine(); }
public void Combine() { Transform[] childTransforms = gameObject.GetComponentsInChildren <Transform> (); foreach (Transform childTransform in childTransforms) { Objects.Add(childTransform.gameObject); } // Find all mesh filter submeshes and separate them by their cooresponding materials ArrayList materials = new ArrayList(); ArrayList combineInstanceArrays = new ArrayList(); foreach (GameObject obj in Objects) { if (!obj) { continue; } MeshFilter[] meshFilters = obj.GetComponentsInChildren <MeshFilter>(); foreach (MeshFilter meshFilter in meshFilters) { MeshRenderer meshRenderer = meshFilter.GetComponent <MeshRenderer>(); // Handle bad input if (!meshRenderer) { Debug.LogError("MeshFilter does not have a coresponding MeshRenderer."); continue; } if (meshRenderer.materials.Length != meshFilter.sharedMesh.subMeshCount) { Debug.LogError("Mismatch between material count and submesh count. Is this the correct MeshRenderer?"); continue; } for (int s = 0; s < meshFilter.sharedMesh.subMeshCount; s++) { int materialArrayIndex = Contains(materials, meshRenderer.sharedMaterials [s].name); if (materialArrayIndex == -1) { materials.Add(meshRenderer.sharedMaterials [s]); materialArrayIndex = materials.Count - 1; } combineInstanceArrays.Add(new ArrayList()); CombineInstance combineInstance = new CombineInstance(); combineInstance.transform = meshRenderer.transform.localToWorldMatrix; combineInstance.subMeshIndex = s; combineInstance.mesh = meshFilter.sharedMesh; (combineInstanceArrays [materialArrayIndex] as ArrayList).Add(combineInstance); } } } // For MeshFilter { // Get / Create mesh filter MeshFilter meshFilterCombine = gameObject.GetComponent <MeshFilter>(); if (!meshFilterCombine) { meshFilterCombine = gameObject.AddComponent <MeshFilter>(); } // Combine by material index into per-material meshes // also, Create CombineInstance array for next step Mesh[] meshes = new Mesh[materials.Count]; CombineInstance[] combineInstances = new CombineInstance[materials.Count]; for (int m = 0; m < materials.Count; m++) { CombineInstance[] combineInstanceArray = (combineInstanceArrays[m] as ArrayList).ToArray(typeof(CombineInstance)) as CombineInstance[]; meshes[m] = new Mesh(); meshes[m].CombineMeshes(combineInstanceArray, true, true); combineInstances[m] = new CombineInstance(); combineInstances[m].mesh = meshes[m]; combineInstances[m].subMeshIndex = 0; } // Combine into one meshFilterCombine.sharedMesh = new Mesh(); meshFilterCombine.sharedMesh.CombineMeshes(combineInstances, false, false); // Destroy other meshes foreach (Mesh mesh in meshes) { mesh.Clear(); DestroyImmediate(mesh); } } // For MeshRenderer { // Get / Create mesh renderer MeshRenderer meshRendererCombine = gameObject.GetComponent <MeshRenderer>(); if (!meshRendererCombine) { meshRendererCombine = gameObject.AddComponent <MeshRenderer>(); } // Assign materials Material[] materialsArray = materials.ToArray(typeof(Material)) as Material[]; meshRendererCombine.materials = materialsArray; } }
void CreatePickingMesh() { var renderer = GetComponent <MeshRenderer>(); var filter = GetComponent <MeshFilter>(); if (!renderer) { var brick = GetComponent <Brick>(); var combineInstances = new List <CombineInstance>(); if (brick) { // Get all shells from parts and combine them. foreach (var part in brick.parts) { if (part.legacy) { var partRenderer = part.GetComponent <MeshRenderer>(); if (partRenderer) { var mesh = partRenderer.GetComponent <MeshFilter>().sharedMesh; var combineInstance = new CombineInstance(); combineInstance.mesh = mesh; combineInstance.transform = transform.worldToLocalMatrix * part.transform.localToWorldMatrix; combineInstances.Add(combineInstance); } } else { var shell = part.transform.Find("Shell"); if (shell) { var mesh = shell.GetComponent <MeshFilter>().sharedMesh; var combineInstance = new CombineInstance(); combineInstance.mesh = mesh; combineInstance.transform = transform.worldToLocalMatrix * shell.localToWorldMatrix; combineInstances.Add(combineInstance); } var colourChangeSurfaces = part.transform.Find("ColourChangeSurfaces"); if (colourChangeSurfaces) { foreach (Transform colourChangeSurface in colourChangeSurfaces) { var mesh = colourChangeSurface.GetComponent <MeshFilter>().sharedMesh; var combineInstance = new CombineInstance(); combineInstance.mesh = mesh; combineInstance.transform = transform.worldToLocalMatrix * colourChangeSurface.localToWorldMatrix; combineInstances.Add(combineInstance); } } } } } Mesh combinedMesh = null; if (combineInstances.Count == 1) { // If there is just one mesh, simply use a reference to that rather than combining. // We know that the one mesh will not be transformed, so it's safe to ignore the transform on the CombineInstance. combinedMesh = combineInstances[0].mesh; } else if (combineInstances.Count > 1) { // Otherwise, if there's more than one, create and save a mesh asset (if it does not exist already). // Then reference that mesh asset. if (!PickingMeshUtils.CheckIfPickingMeshExists(name)) { var newMesh = new Mesh(); newMesh.CombineMeshes(combineInstances.ToArray(), true, true, false); PickingMeshUtils.SavePickingMesh(name, newMesh); combinedMesh = PickingMeshUtils.LoadPickingMesh(name); } else { combinedMesh = PickingMeshUtils.LoadPickingMesh(name); } } else { // If there were no meshes, we assume it is a minifig and use a box mesh. combinedMesh = PickingMeshUtils.LoadMinifigPickingMesh(); } renderer = gameObject.AddComponent <MeshRenderer>(); renderer.sharedMaterial = AssetDatabase.LoadAssetAtPath <Material>("Packages/com.unity.lego.modelimporter/Materials/LEGO_AssetPicking.mat"); filter = gameObject.AddComponent <MeshFilter>(); filter.sharedMesh = combinedMesh; } // Need to hide the renderer, filter and material every time as they do not stay hidden when reloading the scene. renderer.hideFlags = HideFlags.HideInInspector | HideFlags.NotEditable; renderer.sharedMaterial.hideFlags = HideFlags.HideInInspector | HideFlags.NotEditable; filter.hideFlags = HideFlags.HideInInspector | HideFlags.NotEditable; }
void Start() { MeshFilter[] meshFilters = GetComponentsInChildren <MeshFilter>(); MeshRenderer[] meshRenderers = GetComponentsInChildren <MeshRenderer>(); CombineInstance[] combine = new CombineInstance[meshFilters.Length]; //Material[] SharedMats = meshRenderers[1].sharedMaterials; Material MainMaterial = meshRenderers[1].materials[0]; Material[] SubMaterial = new Material[meshRenderers[1].materials.Length - 1]; List <CombineInstance> combine2 = new List <CombineInstance>(); // gotta get this big enough SubMaterial = new Material[2]; for (int i = 0; i < meshFilters.Length; i++) { Mesh mShared = meshFilters[i].sharedMesh; combine[i].mesh = mShared; combine[i].transform = meshFilters[i].transform.localToWorldMatrix; if (mShared.subMeshCount > 1) { // combine submeshes for (int j = 0; j < mShared.subMeshCount; j++) { if (j < mShared.subMeshCount - 1) { SubMaterial[i] = meshRenderers[1].materials[0]; } CombineInstance ci = new CombineInstance(); ci.mesh = mShared; ci.subMeshIndex = j; ci.transform = meshFilters[i].transform.localToWorldMatrix; combine2.Add(ci); } } meshFilters[i].gameObject.SetActive(false); } GameObject go = new GameObject(gameObject.name); go.AddComponent <MeshFilter>(); go.AddComponent <MeshRenderer>(); var goFilter = go.GetComponent <MeshFilter>(); var goRenderer = go.GetComponent <MeshRenderer>(); go.SetActive(false); goFilter.mesh = new Mesh(); goFilter.mesh.CombineMeshes(combine); go.SetActive(true); //goRenderer.materials = Mats; goRenderer.material = MainMaterial; if (SubMaterial.Length >= 1) { GameObject go2 = new GameObject(gameObject.name + "Sub"); go2.AddComponent <MeshFilter>(); go2.AddComponent <MeshRenderer>(); var goFilter2 = go2.GetComponent <MeshFilter>(); var goRenderer2 = go2.GetComponent <MeshRenderer>(); go2.SetActive(false); goFilter2.mesh = new Mesh(); goFilter2.mesh.CombineMeshes(combine2.ToArray(), false); go2.SetActive(true); //goRenderer.materials = Mats; goRenderer2.materials = SubMaterial; } Destroy(gameObject); }
void Start() { // Create an array of CombineInstances to hold tube meshes temporarily. CombineInstance[] combineInstances = new CombineInstance[HAIR_COUNT]; // Temporary variables for calculating positions. float revolutions = 0; float positionRadius = HAIR_RADIUS; // Create tubes. for (int h = 0; h < HAIR_COUNT; h++) { // Create game object and add TubeRenderer component. TubeRenderer tube = new GameObject().AddComponent <TubeRenderer>(); // Position object. revolutions += (HAIR_RADIUS * 2) / (positionRadius * Mathf.PI * 2); positionRadius = revolutions * (HAIR_RADIUS * 2); tube.transform.position = Quaternion.Euler(0, revolutions * 360, 0) * Vector3.forward * positionRadius; // No caps please. tube.caps = TubeRenderer.CapMode.None; // Toggle between two different uv mappings. tube.uvRect = h % 2 == 0 ? new Rect(0.01f, 0.01f, 0.48f, 0.48f) : new Rect(0, 0.51f, 0.48f, 0.48f); // Create points and radiuses arrays. tube.points = new Vector3[POINT_COUNT]; tube.radiuses = new float[POINT_COUNT]; // Calculate height. float hairNorm = h / (HAIR_COUNT - 1f); float height = Mathf.Pow(1 - hairNorm, 0.8f) * 0.5f; // Define points and radiuses. tube.points[0] = Vector3.zero; tube.radiuses[0] = HAIR_RADIUS; for (int p = 1; p < POINT_COUNT; p++) { float norm = (p - 1) / (POINT_COUNT - 2f); float angle = norm * Mathf.PI * 0.5f; tube.radiuses[p] = Mathf.Cos(angle) * HAIR_RADIUS; float y = height + Mathf.Sin(angle) * HAIR_RADIUS; tube.points[p] = new Vector3(0, y, 0); } // Force update to generate the tube mesh immediately. tube.ForceUpdate(); // Add the tube mesh to the combine instances. combineInstances[h].mesh = tube.mesh; combineInstances[h].transform = tube.transform.localToWorldMatrix; // Destroy the TubeRenderer we just used to build the mesh. Destroy(tube.gameObject); } // Add mesh rendering components and combine tubes. gameObject.AddComponent <MeshRenderer>(); MeshFilter filter = gameObject.AddComponent <MeshFilter>(); filter.mesh.CombineMeshes(combineInstances); // Add a material and a texture. GetComponent <Renderer>().material = new Material(Shader.Find("Diffuse")); GetComponent <Renderer>().material.mainTexture = Helpers.CreateTileTexture(2); }
static void CombineCollider() { if (Selection.activeGameObject == null) { return; } MeshFilter[] meshFilters = Selection.activeGameObject.GetComponentsInChildren <MeshFilter>(); if (meshFilters.Length == 0) { return; } List <CombineInstance> combine = new List <CombineInstance>(); var delete = EditorUtility.DisplayDialog("Collider Generator", "Delete Child Collider?", "Yes", "No"); var hadFilter = true; if (Selection.activeGameObject.GetComponent <MeshFilter>() == null) { hadFilter = false; Selection.activeGameObject.AddComponent <MeshFilter>(); } var prevMesh = Selection.activeGameObject.GetComponent <MeshFilter>().sharedMesh; var count = 0; if (Selection.activeGameObject.GetComponent <MeshCollider>()) { DestroyImmediate(Selection.activeGameObject.GetComponent <MeshCollider>()); } for (int i = 0; i < meshFilters.Length; i++) { if (meshFilters[i].sharedMesh == null) { if (delete) { DestroyImmediate(meshFilters[i]); continue; } } var c = new CombineInstance(); c.mesh = meshFilters[i].sharedMesh; c.transform = Selection.activeGameObject.transform.worldToLocalMatrix * meshFilters[i].transform.localToWorldMatrix; combine.Add(c); if (meshFilters[i].GetComponent <Collider>() && delete) { DestroyImmediate(meshFilters[i].GetComponent <Collider>()); } count += meshFilters[i].sharedMesh.vertexCount; if (i + 1 == meshFilters.Length || meshFilters[i + 1].sharedMesh.vertexCount + count > MAXTRISCOUNT) { if (Selection.activeGameObject.GetComponent <MeshFilter>() == null) { Selection.activeGameObject.AddComponent <MeshFilter>(); } Selection.activeGameObject.transform.GetComponent <MeshFilter>().sharedMesh = new Mesh(); Selection.activeGameObject.transform.GetComponent <MeshFilter>().sharedMesh.CombineMeshes(combine.ToArray()); Selection.activeGameObject.AddComponent <MeshCollider>(); combine.Clear(); count = 0; } } if (hadFilter) { Selection.activeGameObject.GetComponent <MeshFilter>().sharedMesh = prevMesh; } else { DestroyImmediate(Selection.activeGameObject.GetComponent <MeshFilter>()); } }
// Update is called once per frame public override void Update() { base.Update(); if (Input.GetMouseButtonDown(0) & !Input.GetKey(KeyCode.LeftControl)) { RaycastHit hit; Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); bool canHit = Physics.Raycast(ray, out hit, 100f); if (canHit) { this.ExtrudeMesh(); } if (Physics.Raycast(ray, out hit, 100f)) { this.pos = hit.transform.position; this.normal = hit.normal; hit.transform.position += hit.normal * this.extrusionSenstivity; RaycastHit u; if (Physics.Raycast(hit.point, -hit.normal, out u)) { Debug.LogError(u.transform.gameObject); this.ScaleSiblingParts(hit.transform.gameObject, u.transform.gameObject, hit.normal, this.scaleSenstivity, this.positionSenstivity); } CombineInstance[] instances = new CombineInstance[this.triangles.Count]; for (int i = 0; i < instances.Length; i++) { instances[i].mesh = this.triangles[i].GetComponent <MeshFilter>().mesh; instances[i].transform = this.triangles[i].GetComponent <MeshRenderer>().transform.localToWorldMatrix; } for (int i = 0; i < this.triangles.Count; i++) { Destroy(this.triangles[i]); } Mesh m = new Mesh(); m.CombineMeshes(instances, true, true); UnityEditor.MeshUtility.Optimize(m); this.meshFilter.mesh = m; this.meshCollider.sharedMesh = m; this.meshRenderer.enabled = true; this.meshCollider.enabled = true; } } if (this.normal != Vector3.zero) { Debug.DrawRay(this.pos, this.normal * 10f, Color.red); } }
/// Создание модели лабиринта Mesh BuildModel() { Mesh wallMesh = Wall(Vector2.zero, new Vector2(.5f, 0), Vector2.up); // половина текстуры Mesh groundMesh = Quad(Vector3.up, Vector3.right, Vector3.forward, new Vector2(.5f, 0), Vector2.right, new Vector2(.5f, .5f)); Mesh roofMesh = Quad(Vector3.down, Vector3.forward, Vector3.right, new Vector2(.5f, .5f), new Vector2(1, .5f), new Vector2(.5f, 1)); Vector3 scale = new Vector3(widthCount, 1, widthCount); Quaternion bottom = Quaternion.identity; Quaternion left = Quaternion.Euler(0, 90, 0); Quaternion top = Quaternion.Euler(0, 180, 0); Quaternion right = Quaternion.Euler(0, -90, 0); CombineInstance[] meshes = new CombineInstance[getMeshesNumber()]; int faceOffset = 0, sX, sZ, lastRow = size * widthCount; // Строим модель лабиринта на основе элементов массива m for (int z = 0; z < size; z++) { for (int x = 0; x < size; x++) { sX = x * widthCount; // scale X sZ = z * widthCount; // scale Y if (m[x, z] == boundary) { if (z > 0 && m[x, z - 1] > boundary) // снизу от текущей клетки { meshes[faceOffset].mesh = wallMesh; meshes[faceOffset].transform = Matrix4x4.TRS(new Vector3(sX, 0, sZ), bottom, Vector3.one); faceOffset++; } if (x > 0 && m[x - 1, z] > boundary) // слева от текущей клетки { meshes[faceOffset].mesh = wallMesh; meshes[faceOffset].transform = Matrix4x4.TRS( new Vector3(sX, 0, sZ + widthCount), left, Vector3.one); faceOffset++; } if (z < size && m[x, z + 1] > boundary) // сверху от текущей клетки { meshes[faceOffset].mesh = wallMesh; meshes[faceOffset].transform = Matrix4x4.TRS( new Vector3(sX + widthCount, 0, sZ + widthCount), top, Vector3.one); faceOffset++; } if (x < size && m[x + 1, z] > boundary) // справа от текущей клетки { meshes[faceOffset].mesh = wallMesh; meshes[faceOffset].transform = Matrix4x4.TRS( new Vector3(sX + widthCount, 0, sZ), right, Vector3.one); faceOffset++; } } else { meshes[faceOffset].mesh = groundMesh; // пол meshes[faceOffset].transform = Matrix4x4.TRS(new Vector3(sX, 0, sZ), bottom, scale); faceOffset++; meshes[faceOffset].mesh = roofMesh; // крыша meshes[faceOffset].transform = Matrix4x4.TRS(new Vector3(sX, heightCount, sZ), bottom, scale); faceOffset++; } } // Наружные стенки sZ = z * widthCount; // scale Z sX = sZ + widthCount; // scale X meshes[faceOffset].mesh = wallMesh; // "нижняя" стенка meshes[faceOffset].transform = Matrix4x4.TRS(new Vector3(sX, 0, 0), top, Vector3.one); faceOffset++; meshes[faceOffset].mesh = wallMesh; // "левая" стенка meshes[faceOffset].transform = Matrix4x4.TRS(new Vector3(0, 0, sZ), right, Vector3.one); faceOffset++; meshes[faceOffset].mesh = wallMesh; // "верхняя" стенка meshes[faceOffset].transform = Matrix4x4.TRS(new Vector3(sZ, 0, lastRow), bottom, Vector3.one); faceOffset++; meshes[faceOffset].mesh = wallMesh; // "правая" стенка meshes[faceOffset].transform = Matrix4x4.TRS(new Vector3(lastRow, 0, sX), left, Vector3.one); faceOffset++; } Mesh mesh = new Mesh(); mesh.CombineMeshes(meshes, true, true); mesh.Optimize(); return(mesh); }
static RuntimeHandles() { LinesMaterial = new Material(Shader.Find("Battlehub/RTHandles/VertexColor")); LinesMaterial.color = Color.white; LinesClipMaterial = new Material(Shader.Find("Battlehub/RTHandles/VertexColorClip")); LinesClipMaterial.color = Color.white; LinesBillboardMaterial = new Material(Shader.Find("Battlehub/RTHandles/VertexColorBillboard")); LinesBillboardMaterial.color = Color.white; ShapesMaterial = new Material(Shader.Find("Battlehub/RTHandles/Shape")); ShapesMaterial.color = Color.white; ShapesMaterialZTest = new Material(Shader.Find("Battlehub/RTHandles/Shape")); ShapesMaterialZTest.color = new Color(1, 1, 1, 0); ShapesMaterialZTest.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.LessEqual); ShapesMaterialZTest.SetFloat("_ZWrite", 1.0f); ShapesMaterialZTestOffset = new Material(Shader.Find("Battlehub/RTHandles/Shape")); ShapesMaterialZTestOffset.color = new Color(1, 1, 1, 1); ShapesMaterialZTestOffset.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.LessEqual); ShapesMaterialZTestOffset.SetFloat("_ZWrite", 1.0f); ShapesMaterialZTestOffset.SetFloat("_OFactors", -1.0f); ShapesMaterialZTestOffset.SetFloat("_OUnits", -1.0f); ShapesMaterialZTest2 = new Material(Shader.Find("Battlehub/RTHandles/Shape")); ShapesMaterialZTest2.color = new Color(1, 1, 1, 0); ShapesMaterialZTest2.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.LessEqual); ShapesMaterialZTest2.SetFloat("_ZWrite", 1.0f); ShapesMaterialZTest3 = new Material(Shader.Find("Battlehub/RTHandles/Shape")); ShapesMaterialZTest3.color = new Color(1, 1, 1, 0); ShapesMaterialZTest3.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.LessEqual); ShapesMaterialZTest3.SetFloat("_ZWrite", 1.0f); ShapesMaterialZTest4 = new Material(Shader.Find("Battlehub/RTHandles/Shape")); ShapesMaterialZTest4.color = new Color(1, 1, 1, 0); ShapesMaterialZTest4.SetFloat("_ZTest", (float)UnityEngine.Rendering.CompareFunction.LessEqual); ShapesMaterialZTest4.SetFloat("_ZWrite", 1.0f); XMaterial = new Material(Shader.Find("Battlehub/RTHandles/Billboard")); XMaterial.color = Color.white; XMaterial.mainTexture = Resources.Load <Texture>("Battlehub.RuntimeHandles.x"); YMaterial = new Material(Shader.Find("Battlehub/RTHandles/Billboard")); YMaterial.color = Color.white; YMaterial.mainTexture = Resources.Load <Texture>("Battlehub.RuntimeHandles.y"); ZMaterial = new Material(Shader.Find("Battlehub/RTHandles/Billboard")); ZMaterial.color = Color.white; ZMaterial.mainTexture = Resources.Load <Texture>("Battlehub.RuntimeHandles.z"); GridMaterial = new Material(Shader.Find("Battlehub/RTHandles/Grid")); GridMaterial.color = Color.white; Mesh selectionArrowMesh = CreateConeMesh(SelectionColor); CombineInstance yArrow = new CombineInstance(); yArrow.mesh = selectionArrowMesh; yArrow.transform = Matrix4x4.TRS(Vector3.up, Quaternion.identity, Vector3.one); SelectionArrowY = new Mesh(); SelectionArrowY.CombineMeshes(new[] { yArrow }, true); SelectionArrowY.RecalculateNormals(); CombineInstance xArrow = new CombineInstance(); xArrow.mesh = selectionArrowMesh; xArrow.transform = Matrix4x4.TRS(Vector3.right, Quaternion.AngleAxis(-90, Vector3.forward), Vector3.one); SelectionArrowX = new Mesh(); SelectionArrowX.CombineMeshes(new[] { xArrow }, true); SelectionArrowX.RecalculateNormals(); CombineInstance zArrow = new CombineInstance(); zArrow.mesh = selectionArrowMesh; zArrow.transform = Matrix4x4.TRS(Vector3.forward, Quaternion.AngleAxis(90, Vector3.right), Vector3.one); SelectionArrowZ = new Mesh(); SelectionArrowZ.CombineMeshes(new[] { zArrow }, true); SelectionArrowZ.RecalculateNormals(); yArrow.mesh = CreateConeMesh(YColor); xArrow.mesh = CreateConeMesh(XColor); zArrow.mesh = CreateConeMesh(ZColor); Arrows = new Mesh(); Arrows.CombineMeshes(new[] { yArrow, xArrow, zArrow }, true); Arrows.RecalculateNormals(); SelectionCube = CreateCubeMesh(SelectionColor, 0.1f, 0.1f, 0.1f); CubeX = CreateCubeMesh(XColor, 0.1f, 0.1f, 0.1f); CubeY = CreateCubeMesh(YColor, 0.1f, 0.1f, 0.1f); CubeZ = CreateCubeMesh(ZColor, 0.1f, 0.1f, 0.1f); CubeUniform = CreateCubeMesh(AltColor, 0.1f, 0.1f, 0.1f); SceneGizmoSelectedAxis = CreateSceneGizmoHalfAxis(SelectionColor, Quaternion.AngleAxis(90, Vector3.right)); SceneGizmoXAxis = CreateSceneGizmoAxis(XColor, AltColor, Quaternion.AngleAxis(-90, Vector3.forward)); SceneGizmoYAxis = CreateSceneGizmoAxis(YColor, AltColor, Quaternion.identity); SceneGizmoZAxis = CreateSceneGizmoAxis(ZColor, AltColor, Quaternion.AngleAxis(90, Vector3.right)); SceneGizmoCube = CreateCubeMesh(AltColor); SceneGizmoSelectedCube = CreateCubeMesh(SelectionColor); SceneGizmoQuad = CreateQuadMesh(); }
// Start is called before the first frame update void Start() { //also from youtube for (int x = 0; x < chunkSizeVerts; x++) { for (int y = 0; y < chunkSizeVerts; y++) { for (int z = 0; z < chunkSizeVerts; z++) { float noise = Perlin3D(x * noiseScale, y * noiseScale, z * noiseScale); if (noise >= threshold) //here we pass floats instead so that Perlin behaves { //sampling unity's perlin noise with an integer returns the same value, which was less than the threshold //Instantiate(blockPrefab, new Vector3(x, y, z), Quaternion.identity);//not rotated is what quaternion.identity says //^^ this is if you treat each point as a cube. I will treat each point as a vertex instead. /*bool xSafe = false; * bool ySafe = false; * bool zSafe = false; * if (x == chunkSize - 1) * { * //check edges (x - 1) * } * else * { * //check edges (x + 1) * } * if (y == chunkSize - 1) * { * //check y edges accordingly * } * else * { * //check edges (y + 1) * } * if (z == chunkSize - 1) * { * //check z edges accordingly * } * else * { * //check edges (z + 1) * } * if (xSafe && ySafe && zSafe) { //make sure that we have checked edges, if all edges are filled, then it is safe to set to 0; we are checking if a cube is like covered or not * chunkData[chunkSize - x - 1, chunkSize - y - 1, z] = 0; * } * else * { * chunkData[chunkSize - x - 1, chunkSize - y - 1, z] = 1; * }*/ chunkData[chunkSizeVerts - x - 1, chunkSizeVerts - y - 1, z] = 1; } else { chunkData[chunkSizeVerts - x - 1, chunkSizeVerts - y - 1, z] = 0;//idk if it instantiates to all 0's } } } } chunkData = hollowOut(chunkData); //now that we have our verticies, lets march some cubes? //some for loop logic to get to one cube //now that we are at a cube: //check each of the 8 verticies to see if it is on or off //index = 0; //for all of the 8 //index += (vertex value [1 or 0]) * 2^(vertex index) //lookup, then make triangle CombineInstance[] wholeMesh = new CombineInstance[(int)Mathf.Pow(chunkSizeBlocks, 3)]; Mesh mesh = GetComponent <MeshFilter>().mesh; mesh.Clear(); int[] initialVoxels = { (int)chunkData[0, 0, 0], (int)chunkData[1, 0, 0], (int)chunkData[1, 0, 1], (int)chunkData[0, 0, 1], (int)chunkData[0, 1, 0], (int)chunkData[1, 1, 0], (int)chunkData[1, 1, 1], (int)chunkData[0, 1, 1] }; Mesh temp = MarchingCubes3.perCube(new Vector3(0, 0, 0), initialVoxels, 0); //foreach (int i in initialVoxels) // Debug.Log(i); //mesh.triangles = temp.triangles; //mesh.vertices = temp.vertices; //mesh.RecalculateBounds(); //mesh.RecalculateNormals(); wholeMesh[0] = new CombineInstance(); wholeMesh[0].mesh = temp; //per chunk for (int x = 0; x < chunkSizeVerts - 1; x++) //or x < chunkSizeBlocks { for (int y = 0; y < chunkSizeVerts - 1; y++) { for (int z = 0; z < chunkSizeVerts - 1; z++) { if (x == 0 && y == 0 && z == 0) { continue; } //set blockNum somehow int blockNum = (int)(z + y * (Mathf.Pow(chunkSizeBlocks, 1)) + x * (Mathf.Pow(chunkSizeBlocks, 2))); //percube int[] voxels = { (int)chunkData[x, y, z], (int)chunkData[x + 1, y, z], (int)chunkData[x + 1, y, z + 1], (int)chunkData[x, y, z + 1], (int)chunkData[x, y + 1, z], (int)chunkData[x + 1, y + 1, z], (int)chunkData[x + 1, y + 1, z + 1], (int)chunkData[x, y + 1, z + 1] }; //this is a line worth checking, I made it match up with MarchingCubes3.localVerticies Mesh m = MarchingCubes3Clean.perCube(new Vector3(0, 0, 0), voxels, blockNum); //^^ this causes unity to freeze up //if combineInstance has too many verts: //IMPLEMENT THIS LOGIC LATER, MAYBE IF COMBINING CHUNKS??? //save the current combineInstance to a mesh //make a new one //Debug.Log(wholeMesh[blockNum]); wholeMesh[blockNum] = new CombineInstance(); wholeMesh[blockNum].mesh = m; //Debug.Log(wholeMesh[blockNum]); //wholeMesh[blockNum].transform. = MarchingCubes3Clean.beginningCoordinates(new Vector3(0, 0, 0), blockNum);//comes with the mesh??? //merge meshes } } } /*mesh.Clear(); * * mesh.CombineMeshes(wholeMesh); * * mesh.RecalculateBounds(); * mesh.RecalculateNormals();*/ //Mesh mesh = GetComponent<MeshFilter>().mesh; mesh = GetComponent <MeshFilter>().mesh; //mesh is invisible now. mesh.Clear(); mesh.CombineMeshes(wholeMesh); //mesh.Optimize(); //MeshCollider meshCollider = GetComponent<MeshCollider>(); //meshCollider.sharedMesh = GetComponent<MeshFilter>().mesh; //this won't work but i want it to :(, also it shows up as black and unlit??? //I think the mesh is centered but idk... mesh.RecalculateBounds(); mesh.RecalculateNormals(); }
public void Start() { if (serializablePieceNumbers != null && serializablePieceNumbers.Length > 0) { piece = Piece.fromSerializable2DIntArray(serializablePieceNumbers); } if (piece == null) { Destroy(gameObject); } // Adding tiles in a wrapper object numberContainer = new GameObject("numbers"); numberContainer.transform.parent = transform; numberContainer.transform.localPosition = new Vector3(0, 0, 0); int[,] pieceNumbers = piece.to2DArray(); Vector3 centerOffset = new Vector3((pieceNumbers.GetLength(1) - 1) / 2.0f, -(pieceNumbers.GetLength(0) - 1) / 2.0f, 0); for (int i = 0; i < piece.getHeight(); i++) { for (int j = 0; j < piece.getWidth(); j++) { // Create quads for valid numbers if (pieceNumbers[i, j] >= 1 && pieceNumbers[i, j] <= 9) { GameObject numberTile = new GameObject(pieceNumbers[i, j] + ""); numberTile.transform.parent = numberContainer.transform; numberTile.transform.localPosition = new Vector3(j, -i, 0) - centerOffset; GameObject quad = GameObject.CreatePrimitive(PrimitiveType.Quad); GameObject backQuad = GameObject.CreatePrimitive(PrimitiveType.Quad); GameObject outlineQuad = GameObject.CreatePrimitive(PrimitiveType.Quad); quad.transform.parent = numberTile.transform; backQuad.transform.parent = numberTile.transform; outlineQuad.transform.parent = numberTile.transform; quad.transform.localPosition = Vector3.zero; backQuad.transform.localPosition = Vector3.zero; outlineQuad.transform.localPosition = new Vector3(0, 0, 0.1f); outlineQuad.transform.localScale = new Vector3(1.05f, 1.05f, 1); // Set the texture to the corresponding number quad.renderer.material = numberSprites[pieceNumbers[i, j] - 1]; quad.renderer.material.color = numberColor; backQuad.renderer.material = backSprite; backQuad.renderer.material.color = backColor; outlineQuad.renderer.material = silhouette; outlineQuad.renderer.material.color = numberColor; Destroy(quad.GetComponent <MeshCollider>()); Destroy(backQuad.GetComponent <MeshCollider>()); Destroy(outlineQuad.GetComponent <MeshCollider>()); numberTile.AddComponent <ForceTileUpright>(); } } } if (!hint) { Vector3 savePosition = transform.position; Quaternion saveRotation = transform.rotation; transform.position = new Vector3(0, 0, 0); transform.rotation = Quaternion.Euler(0, 0, 0); MeshFilter[] meshFilters = GetComponentsInChildren <MeshFilter>(); CombineInstance[] combine = new CombineInstance[meshFilters.Length]; for (int i = 0; i < meshFilters.Length; i++) { combine[i].mesh = meshFilters[i].sharedMesh; combine[i].transform = meshFilters[i].transform.localToWorldMatrix; } MeshFilter meshFilter = gameObject.AddComponent <MeshFilter>(); meshFilter.mesh.CombineMeshes(combine); collider = gameObject.AddComponent <MeshCollider>(); collider.sharedMesh = meshFilter.mesh; transform.position = savePosition; transform.rotation = saveRotation; } targetRotation = Quaternion.Euler(0, 0, 0); StartCoroutine(rotatePiece()); float x = transform.position.x; float y = transform.position.y; float newX = Mathf.Clamp(x, -13, 13); float newY = Mathf.Clamp(y, -10, 5); transform.position = new Vector3(newX, newY, 0); if (hint) { float xOffset = (piece.getWidth() - 1) / 2.0f; float yOffset = (piece.getHeight() - 1) / 2.0f; int correctRow = (int)(piece.getCorrectPosition().y); int correctCol = (int)(piece.getCorrectPosition().x); float correctY = 4 - correctRow - yOffset; float correctX = correctCol - 4 + xOffset; transform.position = new Vector3(correctX, correctY, 0); snapPiece(); } }
public void CreateFromLines(List <Line> _segments) { if (_segments.Count == 0) { return; } Vector3 infiniteRandomPoint = new Vector3(Random.value * 10000.0f + 1000.0f, 0.0f, Random.value * 1000.0f + 10000.0f); List <Line> segments = new List <Line> (); List <Vector3> vbuffer = new List <Vector3> (); // split segment to multiple segments for windows for (int i = 0; i < _segments.Count; i++) { // if (_segments [i].Windows.Count != 0) { // // if (_segments [i].Windows [0].Position.x != 0) { // // int id1 = vbuffer.IndexOf (_segments [i].a); // if (id1 == -1) { // id1 = vbuffer.Count; // vbuffer.Add (_segments [i].a); // } // Vector3 v2 = _segments [i].a + (_segments [i].b - _segments [i].a).normalized * _segments [i].Windows [0].Position.x; // int id2 = vbuffer.IndexOf (v2); // if (id2 == -1) { // id2 = vbuffer.Count; // vbuffer.Add (v2); // } // // Line firstSeg = new Line (vbuffer, id1, id2, _segments[i].Thickness, _segments [i].LineMaterial, _segments [i].InnerMaterial, _segments [i].OuterMaterial, _segments [i].SideMaterial); // firstSeg.Height = _segments [i].Height; // firstSeg.LineType = LineType.Wall; // firstSeg.ParentLine = _segments [i]; // segments.Add (firstSeg); // } // // for (int j = 0; j < _segments[i].Windows.Count - 1; j++) { // Vector3 start = _segments [i].a + (_segments [i].b - _segments [i].a).normalized * _segments [i].Windows [j].Position.x; // Vector3 end = _segments [i].a + (_segments [i].b - _segments [i].a).normalized * (_segments [i].Windows [j].Position.x + _segments [i].Windows [j].WindowWidth); // // int istart = vbuffer.IndexOf (start); // if (istart == -1) { // istart = vbuffer.Count; // vbuffer.Add (start); // } // int iend = vbuffer.IndexOf (end); // if (iend == -1) { // iend = vbuffer.Count; // vbuffer.Add (end); // } // // // Line windowSeg = new Line (vbuffer, istart, iend, _segments[i].Thickness, _segments [i].LineMaterial, _segments [i].InnerMaterial, _segments [i].OuterMaterial, _segments [i].SideMaterial); // windowSeg.LedgeHeight = _segments [i].Windows [j].Position.y; // windowSeg.WindowHeight = _segments [i].Windows [j].WindowHeight; // windowSeg.LineType = LineType.Window; // windowSeg.Height = _segments [i].Height; // windowSeg.ParentLine = _segments [i]; // segments.Add (windowSeg); // // Vector3 nextStart = _segments [i].a + (_segments [i].b - _segments [i].a).normalized * _segments [i].Windows [j + 1].Position.x; // int inextStart = vbuffer.IndexOf (nextStart); // if (inextStart == -1) { // inextStart = vbuffer.Count; // vbuffer.Add (nextStart); // } // Line nextSeg = new Line(vbuffer, iend, inextStart, _segments[i].Thickness, _segments[i].LineMaterial, _segments[i].InnerMaterial, _segments [i].OuterMaterial, _segments [i].SideMaterial); // nextSeg.Height = _segments [i].Height; // nextSeg.LineType = LineType.Wall; // nextSeg.ParentLine = _segments [i]; // segments.Add (nextSeg); // } // // { // Vector3 start = _segments [i].a + (_segments [i].b - _segments [i].a).normalized * _segments [i].Windows [_segments [i].Windows.Count - 1].Position.x; // Vector3 end = _segments [i].a + (_segments [i].b - _segments [i].a).normalized * (_segments [i].Windows [_segments [i].Windows.Count - 1].Position.x + _segments [i].Windows [_segments [i].Windows.Count - 1].WindowWidth); // int istart = vbuffer.IndexOf (start); // if (istart == -1) { // istart = vbuffer.Count; // vbuffer.Add (start); // } // int iend = vbuffer.IndexOf (end); // if (iend == -1) { // iend = vbuffer.Count; // vbuffer.Add (end); // } // // // Line windowSeg = new Line (vbuffer, istart, iend, _segments[i].Thickness, _segments [i].LineMaterial, _segments [i].InnerMaterial, _segments [i].OuterMaterial, _segments [i].SideMaterial); // windowSeg.LedgeHeight = _segments [i].Windows [_segments [i].Windows.Count - 1].Position.y; // windowSeg.WindowHeight = _segments [i].Windows [_segments [i].Windows.Count - 1].WindowHeight; // windowSeg.LineType = LineType.Window; // windowSeg.Height = _segments [i].Height; // windowSeg.ParentLine = _segments [i]; // segments.Add (windowSeg); // // int id2 = vbuffer.IndexOf (_segments [i].b); // if (id2 == -1) { // id2 = vbuffer.Count; // vbuffer.Add (_segments [i].b); // } // // Line lastSeg = new Line(vbuffer, iend, id2, _segments[i].Thickness, _segments[i].LineMaterial, _segments[i].InnerMaterial, _segments [i].OuterMaterial, _segments [i].SideMaterial); // lastSeg.Height = _segments [i].Height; // lastSeg.LineType = LineType.Wall; // lastSeg.ParentLine = _segments [i]; // segments.Add (lastSeg); // } // // // // } else { segments.Add(_segments [i]); } } List <Vector3> segmentsWithContour = Line.Offsets(segments); // lines, lines offseted, lines offseted backward //segments.Clear (); HashSet <Vector3> vertices = new HashSet <Vector3> (); HashSet <int> linesContoured = new HashSet <int> (); // loop all lines, find intersection between offsets on the same side, then replace intersection point Line.WeldIntersections(segmentsWithContour, out vertices); // find end point edges List <Vector3> endpointsSegments = new List <Vector3> (); for (int i = 0; i < segmentsWithContour.Count; i += 6) { if (!vertices.Contains(segmentsWithContour [i])) { endpointsSegments.Add(segmentsWithContour [i + 2]); endpointsSegments.Add(segmentsWithContour [i + 4]); } if (!vertices.Contains(segmentsWithContour [i + 1])) { endpointsSegments.Add(segmentsWithContour [i + 3]); endpointsSegments.Add(segmentsWithContour [i + 5]); } } // remove original lines for (int i = segmentsWithContour.Count - 6; i >= 0; i -= 6) { segmentsWithContour.RemoveAt(i); segmentsWithContour.RemoveAt(i); } // add endpoint edges to contour list segmentsWithContour.AddRange(endpointsSegments); // find directed paths (to determine inner, outer walls) List <List <Vector3> > directedPaths = new List <List <Vector3> >(); directedPaths.Add(new List <Vector3> ()); directedPaths[directedPaths.Count - 1].Add(segmentsWithContour [0]); directedPaths[directedPaths.Count - 1].Add(segmentsWithContour [1]); segmentsWithContour.RemoveRange(0, 2); while (segmentsWithContour.Count > 0) { bool flag = true; for (int i = 0; i < segmentsWithContour.Count; i += 2) { if (directedPaths[directedPaths.Count - 1] [directedPaths[directedPaths.Count - 1].Count - 1] == segmentsWithContour [i]) { directedPaths[directedPaths.Count - 1].Add(segmentsWithContour [i]); directedPaths[directedPaths.Count - 1].Add(segmentsWithContour [i + 1]); segmentsWithContour.RemoveRange(i, 2); flag = false; break; } else if (directedPaths[directedPaths.Count - 1] [directedPaths[directedPaths.Count - 1].Count - 1] == segmentsWithContour [i + 1]) { directedPaths[directedPaths.Count - 1].Add(segmentsWithContour [i + 1]); directedPaths[directedPaths.Count - 1].Add(segmentsWithContour [i]); segmentsWithContour.RemoveRange(i, 2); flag = false; break; } } if (flag) { // to avoid infinite loop // make new directed path directedPaths.Add(new List <Vector3> ()); directedPaths[directedPaths.Count - 1].Add(segmentsWithContour [0]); directedPaths[directedPaths.Count - 1].Add(segmentsWithContour [1]); segmentsWithContour.RemoveRange(0, 2); } } // find outer loop (nearest to infinite) and reverse it if needed for (int i = 0; i < directedPaths.Count; i++) { int minSeg = -1; float dst = float.MaxValue; for (int j = 0; j < directedPaths[i].Count; j += 2) { float det = (directedPaths[i] [j] - Vector3.right * 1000.0f).sqrMagnitude; det += (directedPaths[i] [j + 1] - Vector3.right * 1000.0f).sqrMagnitude; if (det < dst) { dst = det; minSeg = j; } } if (minSeg != -1) { if (Vector3.Dot(Vector3.Normalize(directedPaths [i] [minSeg] - directedPaths [i] [minSeg + 1]), Vector3.forward) < 0) { directedPaths [i].Reverse(); } } } float thicknessSqrd = _segments [0].Thickness * _segments [0].Thickness; //thickness * thickness; List <List <Line> > pathId = new List <List <Line> > (); for (int i = 0; i < directedPaths.Count; i++) { pathId.Add(new List <Line>()); } // for each path find intersection count from (any vertex) to (infinite) which will determine if this is inner or outer wall // then generate walls or windows // destroy line if its for the window (not original line) for (int i = 0; i < directedPaths.Count; i++) { float pathidDst = 0; // bug .. [\] will not work correctly int rand = Random.Range(0, directedPaths[i].Count / 2) * 2; Vector3 randomVertex = Vector3.Lerp(directedPaths [i] [rand], directedPaths [i] [rand + 1], Random.Range(1, 99) / 100.0f); Vector3 randomOutterPoint = new Vector3(Random.Range(10000.0f, 50000.0f), 0, Random.Range(10000.0f, 50000.0f)); int intersectionCount = 0; for (int j = 0; j < directedPaths.Count; j++) { if (i != j) { for (int k = 0; k < directedPaths[j].Count; k += 2) { Vector3 tmp; if (Line.RayRayIntersection(out tmp, directedPaths [j] [k], directedPaths [j] [k + 1], randomVertex, randomOutterPoint)) { if ((tmp - randomOutterPoint).magnitude <= (randomVertex - randomOutterPoint).magnitude) { if ((tmp - directedPaths [j] [k]).magnitude <= (directedPaths [j] [k + 1] - directedPaths [j] [k]).magnitude) { if (Vector3.Dot(tmp - directedPaths [j] [k], directedPaths [j] [k + 1] - directedPaths [j] [k]) >= 0) { intersectionCount++; } } } } } } } if (intersectionCount % 2 == 1) { directedPaths [i].Reverse(); for (int j = 0; j < directedPaths [i].Count; j += 2) { if (Mathf.Abs((directedPaths [i] [j] - directedPaths [i] [j + 1]).sqrMagnitude - thicknessSqrd) <= 0.0001f) { Line l = null; float dst = float.MaxValue; for (int k = 0; k < segments.Count; k++) { float det1 = (segments [k].a - directedPaths [i] [j]).sqrMagnitude; if (det1 < dst) { dst = det1; l = segments [k]; } else { float det2 = (segments [k].b - directedPaths [i] [j]).sqrMagnitude; if (det2 < dst) { dst = det2; l = segments [k]; } } } if (pathId [i].Count == 0) { pathId [i].Add(l.ParentLine == null ? l : l.ParentLine); pathidDst = (infiniteRandomPoint - pathId [i] [0].a).sqrMagnitude + (infiniteRandomPoint - pathId [i] [0].b).sqrMagnitude; } else { Line tmp = l.ParentLine == null ? l : l.ParentLine; float det = (infiniteRandomPoint - tmp.a).sqrMagnitude + (infiniteRandomPoint - tmp.b).sqrMagnitude; if (det > pathidDst) { pathId [i].Clear(); pathidDst = det; pathId [i].Add(tmp); } else if (det == pathidDst) { pathId [i].Add(tmp); } } if (l.ParentLine != null) { l.Destroy(); } } else { Line l = null; float dst = float.MaxValue; for (int k = 0; k < segments.Count; k++) { float det1 = (segments [k].a - directedPaths [i] [j]).sqrMagnitude; det1 += (segments [k].b - directedPaths [i] [j + 1]).sqrMagnitude; if (det1 < dst) { dst = det1; l = segments [k]; } float det2 = (segments [k].b - directedPaths [i] [j]).sqrMagnitude; det2 += (segments [k].a - directedPaths [i] [j + 1]).sqrMagnitude; if (det2 < dst) { dst = det2; l = segments [k]; } } if (pathId [i].Count == 0) { pathId [i].Add(l.ParentLine == null ? l : l.ParentLine); pathidDst = (infiniteRandomPoint - pathId [i] [0].a).sqrMagnitude + (infiniteRandomPoint - pathId [i] [0].b).sqrMagnitude; } else { Line tmp = l.ParentLine == null ? l : l.ParentLine; float det = (infiniteRandomPoint - tmp.a).sqrMagnitude + (infiniteRandomPoint - tmp.b).sqrMagnitude; if (det > pathidDst) { pathId [i].Clear(); pathidDst = det; pathId [i].Add(tmp); } else if (det == pathidDst) { pathId [i].Add(tmp); } } if (l.ParentLine != null) { l.Destroy(); } } } } else { for (int j = 0; j < directedPaths [i].Count; j += 2) { if (Mathf.Abs((directedPaths [i] [j] - directedPaths [i] [j + 1]).sqrMagnitude - thicknessSqrd) <= 0.0001f) { Line l = null; float dst = float.MaxValue; for (int k = 0; k < segments.Count; k++) { float det1 = (segments [k].a - directedPaths [i] [j]).sqrMagnitude; if (det1 < dst) { dst = det1; l = segments [k]; } else { float det2 = (segments [k].b - directedPaths [i] [j]).sqrMagnitude; if (det2 < dst) { dst = det2; l = segments [k]; } } } if (pathId [i].Count == 0) { pathId [i].Add(l.ParentLine == null ? l : l.ParentLine); pathidDst = (infiniteRandomPoint - pathId [i][0].a).sqrMagnitude + (infiniteRandomPoint - pathId [i][0].b).sqrMagnitude; } else { Line tmp = l.ParentLine == null ? l : l.ParentLine; float det = (infiniteRandomPoint - tmp.a).sqrMagnitude + (infiniteRandomPoint - tmp.b).sqrMagnitude; if (det > pathidDst) { pathId [i].Clear(); pathidDst = det; pathId [i].Add(tmp); } else if (det == pathidDst) { pathId [i].Add(tmp); } } if (l.ParentLine != null) { l.Destroy(); } } else { Line l = null; float dst = float.MaxValue; for (int k = 0; k < segments.Count; k++) { float det1 = (segments [k].a - directedPaths [i] [j]).sqrMagnitude; det1 += (segments [k].b - directedPaths [i] [j + 1]).sqrMagnitude; if (det1 < dst) { dst = det1; l = segments [k]; } float det2 = (segments [k].b - directedPaths [i] [j]).sqrMagnitude; det2 += (segments [k].a - directedPaths [i] [j + 1]).sqrMagnitude; if (det2 < dst) { dst = det2; l = segments [k]; } } if (pathId [i].Count == 0) { pathId [i].Add(l.ParentLine == null ? l : l.ParentLine); pathidDst = (infiniteRandomPoint - pathId [i] [0].a).sqrMagnitude + (infiniteRandomPoint - pathId [i] [0].b).sqrMagnitude; } else { Line tmp = l.ParentLine == null ? l : l.ParentLine; float det = (infiniteRandomPoint - tmp.a).sqrMagnitude + (infiniteRandomPoint - tmp.b).sqrMagnitude; if (det > pathidDst) { pathId [i].Clear(); pathidDst = det; pathId [i].Add(tmp); } else if (det == pathidDst) { pathId [i].Add(tmp); } } if (l.ParentLine != null) { l.Destroy(); } } } } } List <Vector3> __Vertices = new List <Vector3> (); List <CombineInstance> combineInstances = new List <CombineInstance> (); List <Material> sideMaterials = new List <Material> (); for (int i = directedPaths.Count - 1; i >= 0; i--) { int dpcount = 0; int secondID = -1; for (int j = 0; j < directedPaths.Count; j++) { if (i >= pathId.Count || j >= pathId.Count) { i--; } if (pathId [i] != null && i != j && helper.anyEqualAny(pathId [i], pathId [j])) { if (dpcount > 2) { throw new UnityException("More than 2 directed pathes for same line !"); } dpcount++; secondID = j; } } if (dpcount == 1) { // find nearest 2 lines from each directed path Vector3 l1v1 = directedPaths [i] [directedPaths [i].Count - 1]; Vector3 l1v2 = directedPaths [i] [directedPaths [i].Count - 2]; directedPaths [i].RemoveAt(directedPaths [i].Count - 1); directedPaths [i].RemoveAt(directedPaths [i].Count - 1); Vector3 tmp = (l1v1 + l1v2) * 0.5f; float dst = float.MaxValue; int selectedj = -1; for (int j = 0; j < directedPaths [secondID].Count; j += 2) { float det = ((directedPaths [secondID] [j] + directedPaths [secondID] [j + 1]) * 0.5f - tmp).sqrMagnitude; if (dst > det) { dst = det; selectedj = j; } } Vector3 l2v1 = directedPaths [secondID] [selectedj]; Vector3 l2v2 = directedPaths [secondID] [selectedj + 1]; directedPaths [secondID].RemoveAt(selectedj); directedPaths [secondID].RemoveAt(selectedj); if ((l2v2 - l1v1).sqrMagnitude < (l2v1 - l1v1).sqrMagnitude) { tmp = l2v1; l2v1 = l2v2; l2v2 = tmp; } List <Line> directedPath = new List <Line> (); for (int j = 0; j < directedPaths [i].Count; j += 2) { int id1 = __Vertices.FindIndex(delegate(Vector3 obj) { return((directedPaths [i] [j] - obj).sqrMagnitude <= 0.0000001f); }); int id2 = __Vertices.FindIndex(delegate(Vector3 obj) { return((directedPaths [i] [j + 1] - obj).sqrMagnitude <= 0.0000001f); }); if (id1 == -1) { id1 = __Vertices.Count; __Vertices.Add(directedPaths [i] [j]); } if (id2 == -1) { id2 = __Vertices.Count; __Vertices.Add(directedPaths [i] [j + 1]); } directedPath.Add(new Line(__Vertices, id1, id2, 1, null, null, null, pathId [i] [0].SideMaterial)); } { int id1 = __Vertices.FindIndex(delegate(Vector3 obj) { return((l1v1 - obj).sqrMagnitude <= 0.0000001f); }); int id2 = __Vertices.FindIndex(delegate(Vector3 obj) { return((l2v1 - obj).sqrMagnitude <= 0.0000001f); }); if (id1 == -1) { id1 = __Vertices.Count; __Vertices.Add(l1v1); } if (id2 == -1) { id2 = __Vertices.Count; __Vertices.Add(l2v1); } directedPath.Add(new Line(__Vertices, id1, id2, 1, null, null, null, pathId [i] [0].SideMaterial)); } { int id1 = __Vertices.FindIndex(delegate(Vector3 obj) { return((l1v2 - obj).sqrMagnitude <= 0.0000001f); }); int id2 = __Vertices.FindIndex(delegate(Vector3 obj) { return((l2v2 - obj).sqrMagnitude <= 0.0000001f); }); if (id1 == -1) { id1 = __Vertices.Count; __Vertices.Add(l1v2); } if (id2 == -1) { id2 = __Vertices.Count; __Vertices.Add(l2v2); } directedPath.Add(new Line(__Vertices, id1, id2, 1, null, null, null, pathId [i] [0].SideMaterial)); } for (int j = 0; j < directedPaths [secondID].Count; j += 2) { int id1 = __Vertices.FindIndex(delegate(Vector3 obj) { return((directedPaths [secondID] [j] - obj).sqrMagnitude <= 0.0000001f); }); int id2 = __Vertices.FindIndex(delegate(Vector3 obj) { return((directedPaths [secondID] [j + 1] - obj).sqrMagnitude <= 0.0000001f); }); if (id1 == -1) { id1 = __Vertices.Count; __Vertices.Add(directedPaths [secondID] [j]); } if (id2 == -1) { id2 = __Vertices.Count; __Vertices.Add(directedPaths [secondID] [j + 1]); } directedPath.Add(new Line(__Vertices, id1, id2, 1, null, null, null, pathId [secondID] [0].SideMaterial)); } // final quad Line.WeldVertices(directedPath); List <int> indices; List <Vector2> uvs; List <Vector3> verts; List <Vector3> normals; try { Line.FillCap(directedPath, out indices, out verts, out uvs, out normals); CombineInstance ci = new CombineInstance(); ci.mesh = new Mesh(); for (int j = 0; j < verts.Count; j++) { verts [j] = new Vector3(verts [j].x, pathId [i] [0].Height, verts [j].z); } ci.mesh.vertices = verts.ToArray(); ci.mesh.uv = uvs.ToArray(); ci.mesh.normals = normals.ToArray(); ci.mesh.SetIndices(indices.ToArray(), MeshTopology.Triangles, 0); ci.transform = Matrix4x4.identity; ci.subMeshIndex = combineInstances.Count; combineInstances.Add(ci); sideMaterials.Add(pathId [i] [0].SideMaterial); pathId.Add(pathId [i]); pathId.RemoveAt(i); pathId.RemoveAt(secondID); directedPaths.RemoveAt(i); directedPaths.RemoveAt(secondID); List <Vector3> finalQuad = new List <Vector3> (); finalQuad.Add(l1v1); finalQuad.Add(l1v2); finalQuad.Add(l2v1); finalQuad.Add(l2v2); finalQuad.Add(l1v1); finalQuad.Add(l2v1); finalQuad.Add(l1v2); finalQuad.Add(l2v2); directedPaths.Add(finalQuad); // pathId.Add (null); // i--; } catch { Debug.Log("Cap Upper wall face !!"); } } else { List <Line> directedPath = new List <Line> (); for (int j = 0; j < directedPaths [i].Count; j += 2) { int id1 = __Vertices.FindIndex(delegate(Vector3 obj) { return((directedPaths [i] [j] - obj).sqrMagnitude <= 0.0000001f); }); int id2 = __Vertices.FindIndex(delegate(Vector3 obj) { return((directedPaths [i] [j + 1] - obj).sqrMagnitude <= 0.0000001f); }); if (id1 == -1) { id1 = __Vertices.Count; __Vertices.Add(directedPaths [i] [j]); } if (id2 == -1) { id2 = __Vertices.Count; __Vertices.Add(directedPaths [i] [j + 1]); } directedPath.Add(new Line(__Vertices, id1, id2, 1, null, null, null, pathId [i] [0].SideMaterial)); } Line.WeldVertices(directedPath); List <int> indices; List <Vector2> uvs; List <Vector3> verts; List <Vector3> normals; try { Line.FillCap(directedPath, out indices, out verts, out uvs, out normals); CombineInstance ci = new CombineInstance(); ci.mesh = new Mesh(); for (int j = 0; j < verts.Count; j++) { verts [j] = new Vector3(verts [j].x, pathId [i] [0].Height, verts [j].z); } ci.mesh.vertices = verts.ToArray(); ci.mesh.uv = uvs.ToArray(); ci.mesh.normals = normals.ToArray(); ci.mesh.SetIndices(indices.ToArray(), MeshTopology.Triangles, 0); ci.transform = Matrix4x4.identity; ci.subMeshIndex = 0; //combineInstances.Count; combineInstances.Add(ci); } catch { Debug.Log("Cap upper wall face !"); } sideMaterials.Add(pathId [i] [0].SideMaterial); } } _filter = this.gameObject.AddComponent <MeshFilter> (); _mesh.Clear(); _mesh.CombineMeshes(combineInstances.ToArray()); update(); _renderer = this.gameObject.AddComponent <MeshRenderer> (); _renderer.materials = sideMaterials.ToArray(); }
public void CombineMeshes(CombineInstance[] combine){}
static void ImportSingle(double OriginX, double OriginY) { double originX = OriginX; double originY = OriginY; string basefilepath = "E:/TiledData/Terrain1000x1000/"; string jsonfilename = originX.ToString() + "-" + originY.ToString() + ".json"; float tileSize = 1000; string filepath = basefilepath; Debug.Log(filepath); if (File.Exists(filepath + jsonfilename)) { CityModel cm = new CityModel(filepath, jsonfilename); //type voetpad Mesh RoadsvoetpadMesh = CreateCityObjectMesh(cm, "Road", originX, originY, tileSize, "bgt_functie", new List <string> { "voetpad", "voetgangersgebied", "ruiterpad", "voetpad op trap" }, true); Mesh LandUseVoetpadMesh = CreateCityObjectMesh(cm, "LandUse", originX, originY, tileSize, "bgt_fysiekvoorkomen", new List <string> { "open verharding" }, true); LandUseVoetpadMesh = SimplifyMesh(LandUseVoetpadMesh, 0.05f); //combine meshes of type "voetpad" CombineInstance[] voetpadcombi = new CombineInstance[2]; voetpadcombi[0].mesh = RoadsvoetpadMesh; voetpadcombi[1].mesh = LandUseVoetpadMesh; Mesh voetpadmesh = new Mesh(); voetpadmesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; voetpadmesh.CombineMeshes(voetpadcombi, true, false); //type fietspad Mesh fietspadMesh = CreateCityObjectMesh(cm, "Road", originX, originY, tileSize, "bgt_functie", new List <string> { "fietspad" }, true); //type parkeervak Mesh parkeervlakMesh = CreateCityObjectMesh(cm, "Road", originX, originY, tileSize, "bgt_functie", new List <string> { "parkeervlak" }, true); //type spoorbaan Mesh spoorbaanMesh = CreateCityObjectMesh(cm, "Road", originX, originY, tileSize, "bgt_functie", new List <string> { "spoorbaan" }, true); //type woonerf Mesh WoonerfMesh = CreateCityObjectMesh(cm, "Road", originX, originY, tileSize, "bgt_functie", new List <string> { "transitie", "woonerf" }, true); // type weg Mesh roadsMesh = CreateCityObjectMesh(cm, "Road", originX, originY, tileSize, "bgt_functie", new List <string> { "fietspad", "parkeervlak", "ruiterpad", "spoorbaan", "voetgangersgebied", "voetpad", "voetpad op trap", "woonerf" }, false); Mesh LandUseVerhardMesh = CreateCityObjectMesh(cm, "LandUse", originX, originY, tileSize, "bgt_fysiekvoorkomen", new List <string> { "gesloten verharding" }, true); LandUseVerhardMesh = SimplifyMesh(LandUseVerhardMesh, 0.05f); // combine meshes of type "weg" CombineInstance[] wegcombi = new CombineInstance[2]; wegcombi[0].mesh = roadsMesh; wegcombi[1].mesh = LandUseVerhardMesh; Mesh wegmesh = new Mesh(); wegmesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; wegmesh.CombineMeshes(wegcombi, true, false); // type groen Mesh plantcoverMesh = CreateCityObjectMesh(cm, "PlantCover", originX, originY, tileSize, "bgt_fysiekvoorkomen", new List <string> { "alles" }, false); Mesh LanduseGroenMesh = CreateCityObjectMesh(cm, "LandUse", originX, originY, tileSize, "bgt_fysiekvoorkomen", new List <string> { "groenvoorziening" }, true); LanduseGroenMesh = SimplifyMesh(LanduseGroenMesh, 0.05f); //combine meshes of type "groen" CombineInstance[] groencombi = new CombineInstance[2]; groencombi[0].mesh = plantcoverMesh; groencombi[1].mesh = LanduseGroenMesh; Mesh groenMesh = new Mesh(); groenMesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; groenMesh.CombineMeshes(groencombi, true, false); //type erf Mesh erfMesh = CreateCityObjectMesh(cm, "LandUse", originX, originY, tileSize, "bgt_fysiekvoorkomen", new List <string> { "erf" }, true); erfMesh = SimplifyMesh(erfMesh, 0.05f); //type onverhard Mesh LandUseMesh = CreateCityObjectMesh(cm, "LandUse", originX, originY, tileSize, "bgt_fysiekvoorkomen", new List <string> { "erf", "groenvoorziening", "gesloten verharding", "open verharding" }, false); LandUseMesh = SimplifyMesh(LandUseMesh, 0.05f); Mesh genericCityObjectMesh = CreateCityObjectMesh(cm, "GenericCityObject", originX, originY, tileSize, "bgt_type", null, true); Mesh waterBodyMesh = CreateCityObjectMesh(cm, "WaterBody", originX, originY, tileSize, "bgt_type", null, true); Mesh bridgeMesh = CreateCityObjectMesh(cm, "Bridge", originX, originY, tileSize, "bgt_type", null, true); //create LOD1 Mesh CombineInstance[] combi = new CombineInstance[12]; combi[0].mesh = voetpadmesh; // combi[1].mesh = fietspadMesh; // combi[2].mesh = parkeervlakMesh; // combi[3].mesh = wegmesh; // combi[4].mesh = groenMesh; // combi[5].mesh = erfMesh; // combi[6].mesh = LandUseMesh; // combi[7].mesh = spoorbaanMesh; // combi[8].mesh = WoonerfMesh; // combi[9].mesh = genericCityObjectMesh; combi[10].mesh = bridgeMesh; combi[11].mesh = waterBodyMesh; ; Mesh lod1Mesh = new Mesh(); lod1Mesh.CombineMeshes(combi, false, false); lod1Mesh.uv2 = RDuv2(lod1Mesh.vertices, CoordConvert.RDtoUnity(new Vector3RD(originX, originY, 0)), tileSize); Physics.BakeMesh(lod1Mesh.GetInstanceID(), false); AssetDatabase.CreateAsset(lod1Mesh, "Assets/terrainMeshes/LOD0/terrain_" + originX + "-" + originY + "-lod1.mesh"); //for debug //GetComponent<MeshFilter>().sharedMesh = lod1Mesh; //create LOD0MEsh combi = new CombineInstance[5]; combi[0].mesh = voetpadmesh; combi[1].mesh = fietspadMesh; combi[2].mesh = parkeervlakMesh; combi[3].mesh = wegmesh; combi[4].mesh = spoorbaanMesh; Mesh Roads = new Mesh(); Roads.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; Roads.CombineMeshes(combi, true, false); Roads = SimplifyMesh(Roads, 0.05f); combi = new CombineInstance[3]; combi[0].mesh = erfMesh; combi[1].mesh = LandUseMesh; combi[2].mesh = WoonerfMesh; Mesh landuse = new Mesh(); landuse.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; landuse.CombineMeshes(combi, true, false); landuse = SimplifyMesh(landuse, 0.05f); combi = new CombineInstance[12]; combi[0].mesh = CreateEmptyMesh(); // combi[1].mesh = CreateEmptyMesh(); // combi[2].mesh = CreateEmptyMesh(); // combi[3].mesh = Roads; // combi[4].mesh = SimplifyMesh(groenMesh, 0.05f); // combi[5].mesh = CreateEmptyMesh(); // combi[6].mesh = landuse; // combi[7].mesh = CreateEmptyMesh(); // combi[8].mesh = CreateEmptyMesh(); // combi[9].mesh = genericCityObjectMesh; combi[10].mesh = bridgeMesh; combi[11].mesh = waterBodyMesh; Mesh lod0Mesh = new Mesh(); lod0Mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32; lod0Mesh.CombineMeshes(combi, false, false); lod0Mesh.uv2 = RDuv2(lod0Mesh.vertices, CoordConvert.RDtoUnity(new Vector3RD(originX, originY, 0)), tileSize); Physics.BakeMesh(lod0Mesh.GetInstanceID(), false); AssetDatabase.CreateAsset(lod0Mesh, "Assets/terrainMeshes/LOD0/terrain_" + originX + "-" + originY + "-lod0.mesh"); } }