//----------------------------------------------------------------------------------- private void UpdateAnimatedByVertexBody( Transform tr, BodyInfo bdInfo ) { BodyMeshInfo bdmeshInfo = (BodyMeshInfo)bdInfo; tr.localPosition = bdmeshInfo.position_; tr.localRotation = bdmeshInfo.orientation_; bool isAnimatedMesh = eManager_.IsBMeshAnimatedByArrPos(bdmeshInfo.idBody_); if ( isAnimatedMesh ) { tr.localScale = Vector3.one; Tuple2<UnityEngine.Mesh, MeshUpdater> meshData = eManager_.GetBodyMeshRenderUpdaterRef(bdInfo.idBody_); UnityEngine.Mesh meshToUpdate = meshData.First; MeshUpdater meshUpdater = meshData.Second; meshToUpdate.vertices = bdmeshInfo.arrVertices_; mcForUpdates.Clear(); mcForUpdates.Set(meshToUpdate, null); CaronteSharp.Tools.UpdateVertexNormalsAndTangents( meshUpdater, mcForUpdates ); meshToUpdate.normals = mcForUpdates.arrNormal_; meshToUpdate.tangents = mcForUpdates.arrTan_; meshToUpdate.RecalculateBounds(); } }
private void SetRgInitForBalltree(GameObject go, Mesh mesh, RgInit rgInit) { rgInit.name_ = go.name; MeshComplex balltreeMC = new MeshComplex(); balltreeMC.Set(mesh); rgInit.meshCollider_Model_ = balltreeMC; Matrix4x4 m_MODEL_to_WORLD = go.transform.localToWorldMatrix; Vector3 scale = m_MODEL_to_WORLD.GetScalePre(); Vector3 normalizedScale = scale / scale.x; Matrix4x4 m_MODEL_to_NORMALIZEDSCALE = Matrix4x4.TRS(Vector3.zero, Quaternion.identity, normalizedScale); rgInit.m_MODEL_to_WORLD_ = m_MODEL_to_NORMALIZEDSCALE; rgInit.useBalltree_ = true; float radius_rate = 1.0f - Data.BalltreeLOD; float radius_rateSq = radius_rate * radius_rate; float radius_rateSqClamped = Mathf.Clamp(radius_rateSq, 0.02f, 1.0f); rgInit.bt_radius_rate_ = radius_rateSqClamped; float requested_resolution1 = 10.0f / Mathf.Pow(radius_rateSqClamped, 5.0f); float requested_resolution2 = 10000.0f * (300.0f - 299.0f * (1.0f - Data.BalltreePrecision)); float mixedResolution = Mathf.Max(requested_resolution1, requested_resolution2); rgInit.bt_resolution_ = (uint)Mathf.Clamp(mixedResolution, 10000.0f, 3000000.0f); rgInit.bt_diameterMaxHoleToCover_rel_ = Mathf.Clamp(Data.BalltreeHoleCovering, 0.0001f, 1.0f); }
public static void CalculateFingerprint(Mesh mesh, byte[] meshFingerprint) { MeshComplex car_mesh = new MeshComplex(); car_mesh.Set(mesh); CaronteSharp.Tools.CalculateMeshFingerprint(car_mesh, meshFingerprint); }
public void Chop() { GameObject[] goToChop = FieldController.GetUnityGameObjects(); int numObjects = goToChop.Length; string errorMessage = string.Empty; if (numObjects == 0) { errorMessage = "Objects field must contain at least one object with geometry"; } if (Data.CropGeometry != null && !Data.CropGeometry.HasMesh()) { errorMessage = "Crop geometry GameObject must contain a mesh"; } if (Data.ChopMode == CNFracture.CHOP_MODE.VORONOI_BY_GEOMETRY) { if (Data.ChopGeometry == null) { errorMessage = "Specifying a steering geometry is mandatory"; } else if (!Data.ChopGeometry.HasMesh()) { errorMessage = "Steering geometry GameObject must contain a mesh"; } } if (Data.ChopMode == CNFracture.CHOP_MODE.VORONOI_RADIAL) { if (Data.ReferenceSystem == null) { errorMessage = "Specifying the reference system is mandatory"; } } if (errorMessage != string.Empty) { EditorUtility.DisplayDialog("CaronteFX", errorMessage, "Ok"); return; } Undo.RecordObject(Data, "Chop - " + Data.Name); List <GameObject> listParentGO = new List <GameObject>(); List <Mesh> listParentMesh_un = new List <Mesh>(); List <MeshComplex> listParentMesh_car = new List <MeshComplex>(); List <Matrix4x4> listMatrixModelToWorld = new List <Matrix4x4>(); for (int i = 0; i < numObjects; i++) { GameObject go = goToChop[i]; Mesh un_mesh = go.GetMesh(); if (un_mesh != null) { MeshComplex mc = new MeshComplex(); mc.Set(un_mesh); listParentMesh_car.Add(mc); listParentMesh_un.Add(un_mesh); listParentGO.Add(go); listMatrixModelToWorld.Add(go.transform.localToWorldMatrix); } } Bounds globalBounds = CREditorUtils.GetGlobalBoundsWorld(listParentGO); ChopRequest cr = new ChopRequest(); cr.doKeepUVCoords_ = true; cr.doKeepVertexNormals_ = true; cr.doParentIndexTriangInfo_ = true; cr.arrMeshToChop_ = listParentMesh_car.ToArray(); cr.arrMatrixModelToWorld_ = listMatrixModelToWorld.ToArray(); cr.doGlobalPattern_ = Data.DoGlobalPattern; cr.seed_ = (uint)Data.Seed; bool chopModeUniform = false; bool chopModeGeometry = false; bool chopModeRadial = false; cr.pProgressFunction_ = null; switch (Data.ChopMode) { case CNFracture.CHOP_MODE.VORONOI_UNIFORM: cr.chopMode_ = CaronteSharp.CP_CHOP_MODE.CP_CHOP_MODE_VORONOI_UNIFORM; chopModeUniform = ChopModeUniform(cr); break; case CNFracture.CHOP_MODE.VORONOI_BY_GEOMETRY: cr.chopMode_ = CaronteSharp.CP_CHOP_MODE.CP_CHOP_MODE_VORONOI_BY_GEOMETRY; chopModeGeometry = ChopModeGeometry(cr); break; case CNFracture.CHOP_MODE.VORONOI_RADIAL: cr.chopMode_ = CaronteSharp.CP_CHOP_MODE.CP_CHOP_MODE_VORONOI_RADIAL; chopModeRadial = ChopModeRadial(cr); break; } if (!chopModeUniform && !chopModeGeometry && !chopModeRadial) { return; } WeldRequest wr = GetWeldRequest(); CaronteSharp.MeshComplex[] arrMeshPieceCaronte; CaronteSharp.MeshParentInfo[] arrMeshParentInfo; Vector3[] arrMeshPosition; ArrayIndex arrInsideOutsideIdx; EditorUtility.DisplayProgressBar(Data.Name, "Chopping...", 1.0f); CaronteSharp.Tools.FractureMeshesV2(cr, wr, out arrMeshPieceCaronte, out arrMeshParentInfo, out arrMeshPosition, out arrInsideOutsideIdx); bool thereIsOutput = arrMeshPieceCaronte.Length > 0; if (cnManager.IsFreeVersion() && !thereIsOutput) { EditorUtility.DisplayDialog("CaronteFX - Free version", "CaronteFX Free version can only fracture the meshes included in the example scenes and the unity primitives (cube, plane, sphere, etc.)", "Ok"); } if (thereIsOutput) { List <GameObject> listChoppedParentGO; CreateListChoppedParentGO(listParentGO, out listChoppedParentGO); EditorUtility.DisplayProgressBar(Data.Name, "Post processing...", 1.0f); UnityEngine.Mesh[] arrMeshPieceUnity; Tuple2 <int, int>[] arrSubmeshRange; int[] arrMeshComplexIdx; CreateMeshPiecesUnity(listChoppedParentGO, arrMeshPieceCaronte, arrMeshParentInfo, arrMeshPosition, out arrMeshPieceUnity, out arrSubmeshRange, out arrMeshComplexIdx); Transform oldParent = DestroyOldObjects(); Undo.RecordObject(Data, "Chop - " + Data.Name); CreateNewObjects(globalBounds.center, listParentGO, listChoppedParentGO, arrMeshParentInfo, arrMeshPieceUnity, arrSubmeshRange, arrMeshComplexIdx, arrMeshPosition, arrInsideOutsideIdx.arrIdx_); if (oldParent != null) { Data.GameObjectChoppedRoot.transform.parent = oldParent; } SeparatePieces(); CalculateStatistics(); EditorUtility.ClearProgressBar(); Undo.SetCurrentGroupName("Chop - " + Data.Name); Undo.CollapseUndoOperations(Undo.GetCurrentGroup()); EditorUtility.SetDirty(Data); } }
public static void TessellateObjects(GameObject[] arrGameObjectToTessellate, float maxEdgeLength, bool limitByMeshDimensions, out GameObject[] arrGameObjectTessellated, out Mesh[] arrMeshTessellated) { int nGameObject = arrGameObjectToTessellate.Length; List <GameObject> listGameObjectTessellated = new List <GameObject>(); List <Mesh> listMeshTessellated = new List <Mesh>(); List <Tuple2 <int, int> > listMeshTessellatedSubmesRange = new List <Tuple2 <int, int> >(); Dictionary <Mesh, List <int> > dictMeshListMeshIdx = new Dictionary <Mesh, List <int> >(); MeshComplex auxMesh = new MeshComplex(); double tssDistance = (double)maxEdgeLength; for (int i = 0; i < nGameObject; i++) { GameObject go = arrGameObjectToTessellate[i]; Mesh mesh = go.GetMesh(); if (mesh != null) { bool alreadyTessellated = dictMeshListMeshIdx.ContainsKey(mesh); if (!alreadyTessellated) { if (limitByMeshDimensions) { Bounds bounds = mesh.bounds; Vector3 size = bounds.size; float minDistance = size.magnitude / 50f; tssDistance = (double)Mathf.Clamp(maxEdgeLength, minDistance, float.MaxValue); } auxMesh.Set(mesh); MeshComplex tessellatedMesh; CaronteSharp.Tools.TessellateMesh(auxMesh, (double)tssDistance, out tessellatedMesh); if (tessellatedMesh == null) { arrGameObjectTessellated = null; arrMeshTessellated = null; return; } Mesh[] auxArrMeshTessellated; Tuple2 <int, int>[] auxArrSubmeshRange; CreateMeshesFromComplex(tessellatedMesh, out auxArrMeshTessellated, out auxArrSubmeshRange); List <int> listMeshTessellatedIdx = new List <int>(); for (int j = 0; j < auxArrMeshTessellated.Length; j++) { Mesh auxMeshTessellated = auxArrMeshTessellated[j]; Tuple2 <int, int> auxSubmeshRange = auxArrSubmeshRange[j]; auxMeshTessellated.name = mesh.name + "_" + j + "_tss"; listMeshTessellatedIdx.Add(listMeshTessellated.Count); listMeshTessellated.Add(auxMeshTessellated); listMeshTessellatedSubmesRange.Add(auxSubmeshRange); } dictMeshListMeshIdx.Add(mesh, listMeshTessellatedIdx); } List <int> listMeshIdx = dictMeshListMeshIdx[mesh]; for (int j = 0; j < listMeshIdx.Count; j++) { GameObject goTessellated = Object.Instantiate <GameObject>(go); goTessellated.name = go.name + "_" + j + "_tss"; goTessellated.transform.parent = go.transform.parent; goTessellated.transform.localPosition = go.transform.localPosition; goTessellated.transform.localRotation = go.transform.localRotation; goTessellated.transform.localScale = go.transform.localScale; int idx = listMeshIdx[j]; Mesh meshTessellated = listMeshTessellated[idx]; MeshFilter mf = goTessellated.GetComponent <MeshFilter>(); if (mf != null) { mf.sharedMesh = meshTessellated; } Renderer rn = goTessellated.GetComponent <Renderer>(); if (rn != null) { Tuple2 <int, int> submeshRange = listMeshTessellatedSubmesRange[idx]; Material[] arrMaterial = rn.sharedMaterials; List <Material> listMaterial = new List <Material>(); for (int k = 0; k < arrMaterial.Length; k++) { if (k >= submeshRange.First && k <= submeshRange.Second) { Material mat = arrMaterial[k]; listMaterial.Add(mat); } } rn.sharedMaterials = listMaterial.ToArray(); } SkinnedMeshRenderer smr = goTessellated.GetComponent <SkinnedMeshRenderer>(); if (smr != null) { smr.sharedMesh = meshTessellated; } listGameObjectTessellated.Add(goTessellated); } } } arrGameObjectTessellated = listGameObjectTessellated.ToArray(); arrMeshTessellated = listMeshTessellated.ToArray(); }