private static void ProcessFaces(ref CMesh lCMesh, Plane lPlane) { CFace lNewFace = new CFace(); lNewFace.Plane = lPlane; lNewFace.Visible = true; int lNewFaceIndex = lCMesh.F.Length; for (int i = 0; i < lCMesh.F.Length; i++) { CFace lF = lCMesh.F[i]; if (lF.Visible) { for (int j = 0; j < lF.Edges.Length; j++) { int lEdgeIndex = lF.Edges[j]; lCMesh.V[lCMesh.E[lEdgeIndex].Vertices[0]].Occurs = 0; lCMesh.V[lCMesh.E[lEdgeIndex].Vertices[1]].Occurs = 0; } int lStart, lEnd; if (GetOpenPolyline(lCMesh, lF, out lStart, out lEnd)) { CEdge lNewEdge = new CEdge(); int lNewEdgeIndex = lCMesh.E.Length; lNewEdge.Vertices = new int[2]; lNewEdge.Vertices[0] = lStart; lNewEdge.Vertices[1] = lEnd; lNewEdge.AddFace(i); lNewEdge.AddFace(lNewFaceIndex); lNewEdge.Visible = true; lF.AddEdge(lNewEdgeIndex); lNewFace.AddEdge(lNewEdgeIndex); lCMesh.AppendEdge(lNewEdge); } lCMesh.F[i] = lF; } } lCMesh.AppendFace(lNewFace); }
private static ClipOperationResult Clip(ref CMesh lCMesh, Plane lPlane) { ClipOperationResult lResult = ProcessVertices(ref lCMesh, lPlane); if (lResult != ClipOperationResult.Mixed) { return(lResult); } ProcessEdges(ref lCMesh, lPlane); ProcessFaces(ref lCMesh, lPlane); return(lResult); }
private static bool GetOpenPolyline(CMesh lCMesh, CFace lF, out int lStart, out int lEnd) { for (int i = 0; i < lF.Edges.Length; i++) { int lEdgeIndex = lF.Edges[i]; lCMesh.V[lCMesh.E[lEdgeIndex].Vertices[0]].Occurs++; lCMesh.V[lCMesh.E[lEdgeIndex].Vertices[1]].Occurs++; } lStart = -1; lEnd = -1; for (int i = 0; i < lF.Edges.Length; i++) { int lEdgeIndex = lF.Edges[i]; int lI0 = lCMesh.E[lEdgeIndex].Vertices[0]; int lI1 = lCMesh.E[lEdgeIndex].Vertices[1]; if (lCMesh.V[lI0].Occurs == 1) { if (lStart == -1) { lStart = lI0; } else if (lEnd == -1) { lEnd = lI0; } } if (lCMesh.V[lI1].Occurs == 1) { if (lStart == -1) { lStart = lI1; } else if (lEnd == -1) { lEnd = lI1; } } } return(lStart != -1); }
public static CMesh CreateConvexPolyhedron(Plane[] lPlanes, Vector3 lCentre, Vector3 lSize) { AMesh lMeshToClip = CreateAMeshBox(lCentre, lSize); CMesh lClippedMesh = new CMesh(lMeshToClip); for (int i = 0; i < lPlanes.Length; i++) { ClipOperationResult lResult = Clip(ref lClippedMesh, lPlanes[i]); if (lResult == ClipOperationResult.AllNegative) { break; } } return(lClippedMesh); }
private static ClipOperationResult ProcessVertices(ref CMesh lCMesh, Plane lPlane) { int lPosCount = 0; int lNegCount = 0; for (int i = 0; i < lCMesh.V.Length; i++) { CVertex lV = lCMesh.V[i]; if (lV.Visible) { lV.Distance = Vector3.Dot(lPlane.Normal, lCMesh.V[i].Position) - lPlane.C; if (lV.Distance >= s_Epsilon) { lPosCount++; } else if (lV.Distance <= -s_Epsilon) { lNegCount++; lV.Visible = false; } else { lV.Distance = 0f; } lCMesh.V[i] = lV; } } if (lNegCount == 0) { return(ClipOperationResult.AllPositive); } if (lPosCount == 0) { return(ClipOperationResult.AllNegative); } return(ClipOperationResult.Mixed); }
public static void ConvertMapToUnityObjects(ConvertMapSettings lSettings) { s_Settings = lSettings; //EditorGUI.BeginChangeCheck(); if (s_Settings.UsingHDRPMaterials) { s_BaseColourMapID = Shader.PropertyToID("_BaseColorMap"); s_EmissionMapID = Shader.PropertyToID("_EmissiveColorMap"); s_EmissionColorID = Shader.PropertyToID("_EmissiveColor"); s_EmissionColorLDRID = Shader.PropertyToID("_EmissiveColor"); s_CutoffEnabledID = Shader.PropertyToID("_EmissiveColor"); s_CutoffAlphaID = Shader.PropertyToID("_AlphaCutoff"); } else { s_BaseColourMapID = Shader.PropertyToID("_MainTex"); s_EmissionMapID = Shader.PropertyToID("_EmissionMap"); s_EmissionColorID = Shader.PropertyToID("_EmissionColor"); s_CutoffEnabledID = Shader.PropertyToID("_EmissiveColor"); s_CutoffAlphaID = Shader.PropertyToID("_Cutoff"); } s_MaterialDic = new Dictionary <string, Material>(s_Settings.TexDefs.Textures.Length); s_MaterialList = new List <Material>(s_Settings.TexDefs.Textures.Length); QMapLevel[] lCurrentLevels = GameObject.FindObjectsOfType <QMapLevel>(); for (int i = 0; i < lCurrentLevels.Length; i++) { GameObject.DestroyImmediate(lCurrentLevels[i].gameObject); } GameObject lLevelObject = new GameObject(s_Settings.MapFile.name); QMapLevel lQMap = lLevelObject.AddComponent <QMapLevel>(); lQMap.EntDefs = s_Settings.EntDefs; lLevelObject.isStatic = true; LevelData lLevelData = MapParser.ParseMapToLevelData(s_Settings.MapFile); int lBrushCount = 0; int lTotalBrushes = 0; for (int i = 0; i < lLevelData.Entities.Length; i++) { lTotalBrushes += lLevelData.Entities[i].Brushes.Length; } List <UEntity> lUEnts = new List <UEntity>(lLevelData.Entities.Length); List <Vector3> lAllVerts = new List <Vector3>(10000); for (int i = 0; i < lLevelData.Entities.Length; i++) { List <Vector3> lEntityVerts = new List <Vector3>(1000); QEntity lQEnt = lLevelData.Entities[i]; EntDef lEntDef = s_Settings.EntDefs.GetDefinition(lQEnt.Classname); GameObject lEntGO = null; UEntity lUEnt = null; if (lEntDef.Classname == null) { lEntGO = new GameObject(i + " NULL Classname"); lUEnt = lEntGO.AddComponent <UEmptyEntity>(); } else if (lEntDef.ConvertedPrefab != null) { lEntGO = GameObject.Instantiate(lEntDef.ConvertedPrefab).gameObject; lEntGO.name = i + " " + lQEnt.Classname; lUEnt = lEntGO.GetComponent <UEntity>(); } else if (lEntDef.RuntimePrefab != null) { lEntGO = new GameObject(i + " " + lQEnt.Classname); lUEnt = lEntGO.AddComponent <UEntity>(); } else { lEntGO = new GameObject(i + " " + lQEnt.Classname); lUEnt = lEntGO.AddComponent <UEmptyEntity>(); } lUEnts.Add(lUEnt); lEntGO.isStatic = lEntDef.IsStatic; lEntGO.layer = lEntDef.EntLayer.LayerIndex; lEntGO.transform.parent = lLevelObject.transform; List <GameObject> lBrushes = new List <GameObject>(); List <ConvexMeshData> lConvexMeshDatas = new List <ConvexMeshData>(); for (int j = 0; j < lQEnt.Brushes.Length; j++) { QBrush lBrush = lQEnt.Brushes[j]; lBrushCount++; CMesh lCMesh = ClipMesh.CreateConvexPolyhedron(lBrush.Planes); List <Vector3> lBrushVertList = new List <Vector3>(); for (int v = 0; v < lCMesh.V.Length; v++) { if (lCMesh.V[v].Visible) { lBrushVertList.Add(lCMesh.V[v].Position); } } Vector3 lMin; Vector3 lMax; GetMinMax(lBrushVertList.ToArray(), out lMin, out lMax); Vector3 lSize = lMax - lMin; Vector3 lMidPointDelta = lMin + lSize * 0.5f; lCMesh = ClipMesh.CreateConvexPolyhedron(lBrush.Planes, lMidPointDelta, lSize + Vector3.one * 0.2f); lBrushVertList.Clear(); for (int v = 0; v < lCMesh.V.Length; v++) { if (lCMesh.V[v].Visible) { lBrushVertList.Add(lCMesh.V[v].Position); } } GetMinMax(lBrushVertList.ToArray(), out lMin, out lMax); lAllVerts.AddRange(lBrushVertList); lEntityVerts.AddRange(lBrushVertList); lSize = lMax - lMin; lMidPointDelta = lMin + lSize * 0.5f; UMeshData lMeshData = lCMesh.GetMeshInformation(lMidPointDelta); Texture[] lTextures = FetchTextures(lMeshData); UpdateMaterials(lTextures); UpdateMeshData(ref lMeshData, lTextures); lConvexMeshDatas.Add(new ConvexMeshData(lMeshData, lMidPointDelta)); Mesh[] lNewMeshes = UMeshCreator.ConvertToMeshes(lMeshData); #if UNITY_EDITOR if (s_Settings.AutoGenerateUV2s) { for (int m = 1; m < lNewMeshes.Length; m++) { UnwrapParam lParam = new UnwrapParam(); lParam.angleError = 0.05f; lParam.areaError = 0.05f; lParam.hardAngle = 85f; lParam.packMargin = 2f; Unwrapping.GenerateSecondaryUVSet(lNewMeshes[m], lParam); } } #endif if (lEntDef.HasCollider || lEntDef.HasMesh) { GameObject lColliderGO = new GameObject("Brush " + j); lBrushes.Add(lColliderGO); if (lEntDef.HasCollider) { lColliderGO.transform.position = lMidPointDelta; lColliderGO.transform.parent = lEntGO.transform; lColliderGO.isStatic = lEntDef.IsStatic; lColliderGO.layer = lEntDef.ColLayer.LayerIndex; MeshCollider lMCollider = lColliderGO.AddComponent <MeshCollider>(); lMCollider.sharedMesh = lNewMeshes[0]; lMCollider.convex = true; lMCollider.isTrigger = lEntDef.IsTrigger; //if (s_Settings.SaveLevelAsAsset) //AssetDatabase.CreateAsset(lNewMeshes[0], GetAssetPath(lEntGO.name, lColliderGO.name, lNewMeshes[0].name)); } if (lEntDef.HasMesh) { for (int m = 1; m < lNewMeshes.Length; m++) { GameObject lMeshGO = new GameObject("Mesh " + (m - 1)); lMeshGO.transform.position = lMidPointDelta; lMeshGO.transform.parent = lColliderGO.transform; lMeshGO.isStatic = lEntDef.IsStatic; lMeshGO.layer = lEntDef.MeshLayer.LayerIndex; MeshFilter lMFilter = lMeshGO.AddComponent <MeshFilter>(); MeshRenderer lMRender = lMeshGO.AddComponent <MeshRenderer>(); lMRender.sharedMaterial = s_MaterialDic[lTextures[m - 1].name]; lMRender.receiveShadows = true; lMRender.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.On; lMRender.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion; lMFilter.mesh = lNewMeshes[m]; //if (s_Settings.SaveLevelAsAsset) //AssetDatabase.CreateAsset(lNewMeshes[m], GetAssetPath(lEntGO.name, lColliderGO.name, lMeshGO.name, lNewMeshes[m].name)); /** * * Add Area Lights * **/ TexDef lTexDef; if (s_Settings.TexDefs.HasDefinition(lTextures[m - 1].name, out lTexDef) && lTexDef.HasAreaLight) { GameObject lAreaLightGO = new GameObject("AreaLight " + (m - 1)); lAreaLightGO.transform.position = lMidPointDelta; lAreaLightGO.transform.parent = lMeshGO.transform; lAreaLightGO.isStatic = lEntDef.IsStatic; //lAreaLightGO.layer = LayerMask.NameToLayer("AreaLight"); lAreaLightGO.AddComponent <DestroyObjectOnSpawn>(); MeshFilter lALMFilter = lAreaLightGO.AddComponent <MeshFilter>(); MeshRenderer lALMRender = lAreaLightGO.AddComponent <MeshRenderer>(); lALMRender.sharedMaterial = s_MaterialDic[lTextures[m - 1].name + "_AreaLightMAT"]; lALMRender.receiveShadows = false; lALMRender.shadowCastingMode = UnityEngine.Rendering.ShadowCastingMode.Off; lALMRender.motionVectorGenerationMode = MotionVectorGenerationMode.ForceNoMotion; Mesh lAreaLightMesh = new Mesh(); FaceInfo[] lFaceInfos = lMeshData.MeshFaceInfos[m]; int lVertCount = 0; int lTriCount = 0; for (int f = 0; f < lFaceInfos.Length; f++) { lVertCount += lFaceInfos[f].Indices.Length; if (lFaceInfos[f].Indices.Length > 2) { lTriCount += lFaceInfos[f].Indices.Length - 2; } } int lTriIndex = 0; Vector3[] lNewVerts = new Vector3[lVertCount]; Vector3[] lNormals = new Vector3[lVertCount]; int[] lTriangles = new int[lTriCount * 3]; int[][] lNewIndices = new int[lFaceInfos.Length][]; int lVertIndex = 0; Vector3[] lPosVerts = lMeshData.PosVertices; Vector3[] lUVVerts = lMeshData.UVVertices; for (int f = 0; f < lFaceInfos.Length; f++) { FaceInfo lFaceInfo = lFaceInfos[f]; Plane lPlane = lFaceInfo.Plane; int[] lIndices = lFaceInfo.Indices; lNewIndices[f] = new int[lIndices.Length]; for (int v = 0; v < lIndices.Length; v++) { Vector3 lVertPos = lPosVerts[lIndices[v]]; Vector3 lVertUV = lUVVerts[lIndices[v]]; lNewVerts[lVertIndex] = (lVertPos * lTexDef.AreaSizeScale) - lPlane.Normal * lTexDef.AreaDisplacement; lNormals[lVertIndex] = -lPlane.Normal; lNewIndices[f][v] = lVertIndex; lVertIndex++; } for (int v = 0; v < lNewIndices[f].Length - 2; v++) { lTriangles[lTriIndex++] = lNewIndices[f][0]; lTriangles[lTriIndex++] = lNewIndices[f][v + 1]; lTriangles[lTriIndex++] = lNewIndices[f][v + 2]; } } lAreaLightMesh.vertices = lNewVerts; lAreaLightMesh.triangles = lTriangles; lAreaLightMesh.normals = lNormals; lAreaLightMesh.RecalculateTangents(); lAreaLightMesh.RecalculateBounds(); lAreaLightMesh.name = "Area Light Mesh"; #if UNITY_EDITOR Unwrapping.GenerateSecondaryUVSet(lAreaLightMesh); // TODO May be always needed #endif lALMFilter.mesh = lAreaLightMesh; //if (s_Settings.SaveLevelAsAsset) //AssetDatabase.CreateAsset(lAreaLightMesh, GetAssetPath(lEntGO.name, lColliderGO.name, lMeshGO.name, lAreaLightMesh.name)); } } } } } { List <Vector3> lConvexVertList = new List <Vector3>(); List <FaceInfo> lFaceList = new List <FaceInfo>(); int lIndexShift = 0; for (int c = 0; c < lConvexMeshDatas.Count; c++) { int lVertCount = lConvexMeshDatas[c].MeshData.PosVertices.Length; Vector3 lDeltaPos = lConvexMeshDatas[c].DeltaPos; for (int v = 0; v < lVertCount; v++) { lConvexVertList.Add(lConvexMeshDatas[c].MeshData.PosVertices[v] + lDeltaPos); } for (int f = 0; f < lConvexMeshDatas[c].MeshData.FaceInfos.Length; f++) { FaceInfo lInfo = lConvexMeshDatas[c].MeshData.FaceInfos[f]; for (int fi = 0; fi < lInfo.Indices.Length; fi++) { lInfo.Indices[fi] += lIndexShift; } lFaceList.Add(lInfo); } lIndexShift += lVertCount; } Vector3 lMin, lMax; GetMinMax(lConvexVertList.ToArray(), out lMin, out lMax); Vector3 lSize = lMax - lMin; Vector3 lMidPoint = lMin + lSize * 0.5f; for (int v = 0; v < lConvexVertList.Count; v++) { lConvexVertList[v] -= lMidPoint; } UMeshData lConvexData = new UMeshData(); lConvexData.PosVertices = lConvexData.UVVertices = lConvexVertList.ToArray(); lConvexData.MeshFaceInfos = new FaceInfo[1][]; lConvexData.MeshFaceInfos[0] = lFaceList.ToArray(); if (lEntDef.HasConvexCollider && lConvexMeshDatas.Count > 0) { Mesh[] lConvexMesh = UMeshCreator.ConvertToMeshes(lConvexData); //if (!AssetDatabase.IsValidFolder("Assets/" + s_Settings.MapFile.name)) //AssetDatabase.CreateFolder("Assets", s_Settings.MapFile.name); //AssetDatabase.CreateAsset(lConvexMesh[0], "Assets/" + s_Settings.MapFile.name + "/OriginalMesh.asset"); MeshCollider lMCollider = lUEnt.gameObject.AddComponent <MeshCollider>(); lMCollider.sharedMesh = lConvexMesh[0]; lMCollider.convex = true; lMCollider.isTrigger = lEntDef.IsConvexTrigger; //if (s_Settings.SaveLevelAsAsset) //AssetDatabase.CreateAsset(lConvexMesh[0], GetAssetPath(lEntGO.name, "CONVEX", lConvexMesh[0].name)); } if (lQEnt.Classname == "volume_enemy_spawn") { bool lWhat = true; } lUEnt.Extents = new Extents3D(lMidPoint, lSize); lUEnt.SetupEntity(lQEnt); Vector3 lValue; if (lUEnt.GetValue("origin", out lValue)) { lUEnt.transform.position = lValue; } else if (lBrushes.Count > 0) { for (int b = 0; b < lBrushes.Count; b++) { lBrushes[b].transform.localPosition = lBrushes[b].transform.position - lMidPoint; } lUEnt.transform.position = lMidPoint; } } } Vector3 lAllMin, lAllMax; GetMinMax(lAllVerts.ToArray(), out lAllMin, out lAllMax); Vector3 lAllSize = lAllMax - lAllMin; Vector3 lAllCenter = lAllMin + lAllSize * 0.5f; lQMap.Extents = new Extents3D(lAllCenter, lAllSize); //var lSO = new SerializedObject(lLevelObject); //if (lSO.ApplyModifiedProperties()) //{ // bool lBreakpoint = false; //} //if (s_Settings.SaveLevelAsAsset) //{ bool lSuccess; //for (int i = 0; i < s_MaterialList.Count; i++) //AssetDatabase.CreateAsset(s_MaterialList[i], "Assets/" + s_Settings.MapFile.name + "_MAT " + i + ".asset"); //PrefabUtility.SaveAsPrefabAsset(lLevelObject, "Assets/" + s_Settings.MapFile.name + ".prefab", out lSuccess); //AssetDatabase.Refresh(); //AssetDatabase.SaveAssets(); //} //if (EditorGUI.EndChangeCheck()) //{ // bool lBreakpoint = false; //} #if UNITY_EDITOR EditorSceneManager.MarkSceneDirty(EditorSceneManager.GetActiveScene()); #endif }
private static void ProcessEdges(ref CMesh lCMesh, Plane lPlane) { for (int i = 0; i < lCMesh.E.Length; i++) { CEdge lE = lCMesh.E[i]; if (lE.Visible) { float lD0 = lCMesh.V[lE.Vertices[0]].Distance; float lD1 = lCMesh.V[lE.Vertices[1]].Distance; if (lD0 <= 0f && lD1 <= 0f) { for (int j = 0; j < lE.Faces.Length; j++) { CFace lF = lCMesh.F[lE.Faces[j]]; lF.RemoveEdge(i); if (lF.Edges.Length == 0) { lF.Visible = false; } lCMesh.F[lE.Faces[j]] = lF; } lE.Visible = false; lCMesh.E[i] = lE; continue; } if (lD0 >= 0f && lD1 >= 0f) { lCMesh.E[i] = lE; continue; } float lT = lD0 / (lD0 - lD1); Vector3 lDelta0 = (1f - lT) * lCMesh.V[lE.Vertices[0]].Position; Vector3 lDelta1 = lT * lCMesh.V[lE.Vertices[1]].Position; Vector3 lIntersect = lDelta0 + lDelta1; int lIndex = lCMesh.V.Length; CVertex lNewVertex = new CVertex(lIntersect); lCMesh.AppendVertex(lNewVertex); if (lD0 > 0) { lE.Vertices[1] = lIndex; } else { lE.Vertices[0] = lIndex; } lCMesh.E[i] = lE; } } }