public void StartBuilding(MeshFilter mf, ModuleCarnationVariablePart variablePart) { cvsp = variablePart; buildStarted = true; for (int i = 0; i < isSectionVisible.Length; i++) { isSectionVisible[i] = true; } mesh = mf.mesh; if (mesh == null || !mesh.isReadable) { Debug.Log("[CRFP] Creating new mesh, Mesh readable:" + (mesh == null ? "Null" : (mesh.isReadable).ToString())); mf.mesh = new Mesh(); mesh = mf.mesh; mesh.vertices = originSectionVerts; mesh.triangles = originSectionTris; mesh.uv = originSectionUV; InstantiateMesh(); } else { InstantiateMesh(); } }
public void FinishBuilding(ModuleCarnationVariablePart variablePart) { //if (cvsp != variablePart) // Debug.LogError("[CRFP] CVSP build process is interrupted!"); ////else //// cvsp = null; //if (!buildStarted) // Debug.LogError("[CRFP] There's no build process to end!"); buildStarted = false; }
public Texture2D RenderSectionPreview(SectionInfo info, ModuleCarnationVariablePart current) { Texture2D result = new Texture2D(128, 128, TextureFormat.RGBA32, mipCount: 0, linear: false); cvsp.Section0Width = info.width; cvsp.Section0Height = info.height; int i = -1; while (++i < 4) { cvsp.SetCornerRadius(i, info.radius[i]); string name = info.corners[i]; if (name == null) { continue; } SectionCorner corner = CVSPConfigs.SectionCornerDefinitions.FirstOrDefault(q => q.name.Equals(name)); if (corner.name == null) { continue; } cvsp.SetCornerTypes(corner, i); cvsp.SetCornerTypes(corner, i + 4); } //cvsp.uiEditing = true; if (cvsp.enabled) { cvsp.enabled = false; cvsp.MeshRender.sharedMaterials = new Material[2] { renderMat, renderMat }; Destroy(cvsp.GetComponent <Collider>()); } if (!current) { renderMat.mainTexture = null; } else { renderMat.mainTexture = current.EndsDiffTexture; } cvsp.UpdateSectionTransforms(); cvsp.ForceUpdateGeometry(updateColliders: false); camera.orthographicSize = Mathf.Max(info.width, info.height) / 2; cvsp.MeshRender.enabled = true; camera.Render(); RenderTexture.active = rt; result.ReadPixels(new Rect(0, 0, 128, 128), 0, 0); cvsp.MeshRender.enabled = false; result.Apply(false, true); return(result); }
internal static void RF_UpdateVolume(ModuleCarnationVariablePart cvsp, float totalVolume) { var mft = cvsp.part.FindModuleImplementing <ModuleFuelTanks>(); if (mft == null) { Debug.LogError("[CRFP] RF's component ModuleFuelTanks is not found on the part"); return; } mft.ChangeTotalVolume(totalVolume * CVSPConfigs.RealFuelVolumeFactor); }
/// <summary> /// 只考虑了x、z坐标 /// </summary> /// <param name="v1"></param> /// <param name="v2"></param> /// <param name="param"></param> /// <param name="section">截面编号,0~1</param> /// <returns></returns> private float ScaledDistance(Vector3 v1, Vector3 v2, ModuleCarnationVariablePart param, int section, Quaternion qTiltRotInverse0, Quaternion qTiltRotInverse1) { v1.x -= v2.x; v1.y -= v2.y; v1.z -= v2.z; v1 = section == 0 ? qTiltRotInverse0 * v1 : qTiltRotInverse1 * v1; if (IsZero(v1.x) && IsZero(v1.z) && IsZero(v1.y)) { return(0f); } v1.z /= Mathf.Max(0.0001f, (section == 0 ? param.Section0Height : param.Section1Height) / 2f); v1.x /= Mathf.Max(0.0001f, (section == 0 ? param.Section0Width : param.Section1Width) / 2f); return(Mathf.Sqrt(v1.x * v1.x + v1.z * v1.z)); }
internal static bool FAR_UpdateCollider(ModuleCarnationVariablePart cvsp) { //EditorGUI.RequestUpdateVoxel(); var far = cvsp.part.FindModuleImplementing <GeometryPartModule>(); if (!far) { return(false); } if (RebuildAllMeshData == null) { RebuildAllMeshData = typeof(GeometryPartModule).GetMethod("RebuildAllMeshData", BindingFlags.Instance | BindingFlags.NonPublic); } RebuildAllMeshData.Invoke(far, null); return(true); }
public void Update(ModuleCarnationVariablePart c, Vector4 section0Radius, Vector4 section1Radius, SectionCorner[] cornerTypes, int[] subdivideLevels) { if (c != cvsp) { FinishBuilding(cvsp); StartBuilding(c.Mf, c); } /* if (!BuildingCVSPForFlight) * { * GetNow(); * BuildingCVSPForFlight = true; * MeshesBuiltForFlight = 0; * }*/ RoundRadius[0] = section0Radius.x; RoundRadius[1] = section0Radius.y; RoundRadius[2] = section0Radius.z; RoundRadius[3] = section0Radius.w; RoundRadius[4] = section1Radius.x; RoundRadius[5] = section1Radius.y; RoundRadius[6] = section1Radius.z; RoundRadius[7] = section1Radius.w; //扭转Twist和倾斜Tilt的四元数,代表了截面1的旋转 qSection1Rotation = Quaternion.AngleAxis(cvsp.Twist, Vector3.up) * Quaternion.AngleAxis(cvsp.Tilt1, Vector3.right); qSection1InverseRotation = Quaternion.Inverse(qSection1Rotation); qSection0Rotation = Quaternion.AngleAxis(cvsp.Tilt0, Vector3.right); qSection0InverseRotation = Quaternion.Inverse(qSection0Rotation); for (int i = 0; i < RoundRadius.Length; i++) { BuildSectionCorner(i, Mathf.Abs(RoundRadius[i]), cornerTypes[i]); } for (int i = 0; i < RoundRadius.Length; i++) { oldRoundRadius[i] = RoundRadius[i]; } OptimizeSections(); ModifySections(); CalculatesForUIDisplay(); BuildBody(cornerTypes, subdivideLevels); CorrectSectionUV(); MergeSectionAndBody(); var sepa = sectionTris.Length - DeleteHiddenSection(); Optimize(sepa); // MeshesBuiltForFlight++; }
/// <summary> /// 使用0和1两组顶点索引,编织一个网格带。网格带的中部可以由r0和r1控制生成一个棱 /// </summary> /// <param name="verts">顶点坐标数组</param> /// <param name="vertID0">0组的顶点索引。算法按照棱在正中间编写,两边的三角形数相同,所以一侧点的数目必须为奇数</param> /// <param name="vertID1">1组的顶点索引。长度完全等于前一个索引数组</param> /// <param name="r0">0组的角部圆角。</param> /// <param name="r1">1组的角部圆角。</param> /// <param name="uvStartU0">0组上的顶点起始UV坐标x。</param> /// <param name="uvStartU1">1组上的顶点起始UV坐标x</param> /// <param name="uv0">输出0组上的顶点中止UV坐标x。</param> /// <param name="uv1">输出1组上的顶点中止UV坐标x。</param> /// <param name="param">提供一些UV参数。</param> /// <param name="subdivideLevel0">0组一侧的细分等级,2的幂0</param> /// <param name="subdivideLevel1">1组一侧的细分等级,2的幂0</param> /// <param name="uvStartV0">0组一侧贴图坐标V值</param> /// <param name="uvStartV1">1组一侧贴图坐标V值</param> public void MakeStrip(Vector3[] verts, int[] vertID0, int[] vertID1, float r0, float r1, float uvStartU0, float uvStartU1, out float uv0, out float uv1, ModuleCarnationVariablePart param, int subdivideLevel0, int subdivideLevel1, float uvStartV0, float uvStartV1, Quaternion qTiltRotInverse0, Quaternion qTiltRotInverse1, SectionCorner[] cornerTypes) { this.subdivideLevel = Mathf.Max(subdivideLevel0, subdivideLevel1); //只有当细分等级为0,才去真正创建网格,否则细分给子网格去做 if (subdivideLevel == 0) { float uvCopy0 = uvStartU0, uvCopy1 = uvStartU1; //对尺寸有0时,特殊处理 if (IsZero(param.Section0Height) && Id % 2 == 0) { uvStartU0 += param.SideScaleU; } if (IsZero(param.Section0Width) && Id % 2 == 1) { uvStartU0 += param.SideScaleU; } if (IsZero(param.Section1Height) && Id % 2 == 0) { uvStartU1 += param.SideScaleU; } if (IsZero(param.Section1Width) && Id % 2 == 1) { uvStartU1 += param.SideScaleU; } R0 = r0; R1 = r1; //是否重新划分三角形,详见后文 reTriangulate = Math.Abs(R0) > Math.Abs(R1); additionVert = 0; if (IsZero(R0)) { additionVert++; } if (IsZero(R1)) { additionVert++; } vertices = new Vector3[vertID0.Length + vertID1.Length + additionVert]; //normals = new Vector3[vertID0.Length + vertID1.Length + addition]; uv = new Vector2[vertID0.Length + vertID1.Length + additionVert]; triangles = new int[(vertID0.Length - 1) * 6]; if (vertID0.Length != vertID1.Length) { Debug.LogError("[BodyEdgeBild]ERROR: vertID0.Length != vertID1.Length"); } for (int i = 0; i / 2 < vertID0.Length - 1; i += 2)//遍历vertID0.Length-1个四边形 { //先分配顶点,一个quad4个,但是因为quad间共享一条边,只在遍历第一个quad时分配4个顶点,往后的情况只分配俩 for (int j = i == 0 ? 0 : 2; j < 4; j++) { //第一个quad为例:0、2号顶点在0号截面上,1、3号在1号截面上。0、2号顶点对应vertID0的第0、1号ID,1、3号顶点对应vertID1的第0、1号ID。 vertices[i + j] = verts[j % 2 == 1 ? vertID1[(i + j) / 2] : vertID0[(i + j) / 2]]; //分配起始uv,仅在第一个quad执行 if (j < 2) { uv[j].y = j == 1 ? uvStartV1 : uvStartV0; uv[j].x = j == 1 ? uvStartU1 : uvStartU0; uv[j].x *= 0.5f; } } //边长,用于UV计算 float length0; float length1; if (param.RealWorldMapping) { //使用实际边长计算UV,真实世界贴图坐标 length0 = Vector3.Distance(vertices[i], vertices[i + 2]); length1 = Vector3.Distance(vertices[i + 1], vertices[i + 3]); } else { //使用矫正的边长计算UV length0 = ScaledDistance(vertices[i], vertices[i + 2], param, 0, qTiltRotInverse0, qTiltRotInverse1); length1 = ScaledDistance(vertices[i + 1], vertices[i + 3], param, 1, qTiltRotInverse0, qTiltRotInverse1); } if (param.CornerUVCorrection) { if (i > 0 && i / 2 < vertID0.Length - 2) { //矫正圆角处的UV,达到圆角大小改变,圆角处UV增量也不变的效果 length0 *= PerimeterSharp / cornerTypes[Id].cornerPerimeter; length1 *= PerimeterSharp / cornerTypes[Id + 4].cornerPerimeter; } } //UV增加一个边长 uvStartU0 += length0 * param.SideScaleU; uvStartU1 += length1 * param.SideScaleU; for (int j = 2; j < 4; j++) { //分配UV uv[i + j].y = 1 == j % 2 ? uvStartV1 : uvStartV0; uv[i + j].x = j == 3 ? uvStartU1 : uvStartU0; uv[i + j].x *= 0.5f; } //四边形使用两种不同的三角划分,改善外观(大部分时候改善效果有限) int im3 = i * 3; if ((!reTriangulate && i < vertID0.Length - 1) || (reTriangulate && i >= vertID0.Length - 1)) { triangles[im3] = i; triangles[im3 + 1] = i + 1; triangles[im3 + 2] = i + 2; triangles[im3 + 3] = i + 1; triangles[im3 + 4] = i + 3; triangles[im3 + 5] = i + 2; } else { triangles[im3] = i; triangles[im3 + 1] = i + 1; triangles[im3 + 2] = i + 3; triangles[im3 + 3] = i; triangles[im3 + 4] = i + 3; triangles[im3 + 5] = i + 2; } } if (param.RealWorldMapping) { uv0 = uvStartU0; uv1 = uvStartU1; } else { //直接+2,不用计算边长累加的结果,避免截面尺寸为零时出错 uv0 = uvCopy0 + 2f * param.SideScaleU; uv1 = uvCopy1 + 2f * param.SideScaleU; } //已经录入的顶点个数 int index = vertID0.Length + vertID1.Length - 1; //下面对有锐棱出现的情况进行处理 if (IsZero(R0)) { /* //R0==0的话,一定reTriangulate为false * //角点对应编号:vertID0.Length - 1,影响位于中部的1个三角形:第vertID0.Length - 1 * index++; * //新增(分割)点和uv到数组结尾 * vertices[index] = VectorCopy(vertices[vertID0.Length - 1]); * uv[index] = VectorCopy(uv[vertID0.Length - 1]); * //修改分割处两边的两个三角形 * var triID = vertID0.Length - 1; * triangles[triID * 3] = index; * triangles[triID * 3 + 3] = index;*/ } if (IsZero(R1)) { if (IsZero(R0)) { //R0==0的话,一定reTriangulate为false //角点对应编号:vertID0.Length,影响位于中间的1个三角形:第vertID0.Length - 1 index++; //新增(分割)点和uv到数组结尾 vertices[index] = VectorCopy(vertices[vertID0.Length]); uv[index] = VectorCopy(uv[vertID0.Length]); var triID = vertID0.Length - 1; triangles[triID * 3 + 1] = index; } } CVSPMeshBuilder.RecalculateNormals(vertices, triangles, ref normals); CVSPMeshBuilder.RecalculateTangents(vertices, uv, triangles, ref tangents); } else { if (child0 == null) { child0 = new CVSPBodyEdge(Id); } if (child1 == null) { child1 = new CVSPBodyEdge(Id); } var verts0 = (Vector3[])verts.Clone(); var verts1 = (Vector3[])verts.Clone(); int l = vertID1.Length; for (int i = 0; i < l; i++) { Vector3 mid = Vector3.Lerp(verts[vertID0[i]], verts[vertID1[i]], .5f); verts0[vertID1[i]] = mid; verts1[vertID0[i]] = mid; } //计算分开处的一些参数 var uvStartMid = (uvStartU0 + uvStartU1) / 2f; var rMid = (r0 + r1) / 2f; var sLvlMid = Mathf.Min(subdivideLevel0, subdivideLevel1) / 2; var vMid = (uvStartV0 + uvStartV1) / 2f; child0.MakeStrip(verts0, vertID0, vertID1, r0, rMid, uvStartU0, uvStartMid, out uv0, out _, param, subdivideLevel0 / 2, sLvlMid / 2, uvStartV0, vMid, qTiltRotInverse0, qTiltRotInverse1, cornerTypes); child1.MakeStrip(verts1, vertID0, vertID1, rMid, r1, uvStartMid, uvStartU1, out _, out uv1, param, sLvlMid / 2, subdivideLevel1 / 2, vMid, uvStartV1, qTiltRotInverse1, qTiltRotInverse1, cornerTypes); } }
/// <summary> /// 规范法线,保证过渡区域外观 /// </summary> /// <param name="n1">截面0上开头点的法线</param> /// <param name="n2">截面0上结束点的法线</param> /// <param name="n3">截面1上开头点的法线</param> /// <param name="n4">截面1上结束点的法线</param> internal void SetEndsNorms(Vector3 n1, Vector3 n2, Vector3 n3, Vector3 n4, float r0, float r1, ModuleCarnationVariablePart param) { //只有当细分等级为0,才去真正修改法线,否则细分给子网格去做 if (subdivideLevel == 0) { //截面0一侧的首尾4个点 if (IsZero(1f - r0)) { normals[0] = n1; normals[2] = n1; normals[normals.Length - additionVert - 4] = n2; normals[normals.Length - additionVert - 2] = n2; } else { CopyXZComponent(n1, ref normals[0]); CopyXZComponent(n1, ref normals[2]); CopyXZComponent(n2, ref normals[normals.Length - additionVert - 4]); CopyXZComponent(n2, ref normals[normals.Length - additionVert - 2]); } if (!IsZero(1f - r1)) { CopyXZComponent(n3, ref normals[1]); CopyXZComponent(n3, ref normals[3]); CopyXZComponent(n4, ref normals[normals.Length - additionVert - 3]); CopyXZComponent(n4, ref normals[normals.Length - additionVert - 1]); } else { normals[1] = n3; normals[3] = n3; normals[normals.Length - additionVert - 3] = n4; normals[normals.Length - additionVert - 1] = n4; } CorrectTangent(0); CorrectTangent(2); CorrectTangent(normals.Length - additionVert - 4); CorrectTangent(normals.Length - additionVert - 2); CorrectTangent(1); CorrectTangent(3); CorrectTangent(normals.Length - additionVert - 3); CorrectTangent(normals.Length - additionVert - 1); } else { Vector3 midStart = Vector3.Lerp(n1, n3, .5f); Vector3 midEnd = Vector3.Lerp(n2, n4, .5f); float midR = (r0 + r1) / 2f; child0.SetEndsNorms(n1, n2, midStart, midEnd, r0, midR, param); child1.SetEndsNorms(midStart, midEnd, n3, n4, midR, r1, param); } }