public override double calcVolumeFactor() { double volume = 0; var pp = new Vector2(radialFactor, 0); var slope = new BezierSlope(coneShape); for (int i = 1; i <= heightSegments; ++i) { float v = (float)i / heightSegments; Vector2 p; if (radialFactor <= topFactor) { p = slope.interp(v); p.x = Mathf.Lerp(radialFactor, topFactor, p.x); } else { p = slope.interp(1 - v); p.y = 1 - p.y; p.x = Mathf.Lerp(topFactor, radialFactor, p.x); } double r = (p.x + pp.x) * 0.5; volume += r * r * (p.y - pp.y); pp = p; } return volume * stretchFactor * volMultiplier * utilization / 0.8692f; }
public override void rescaleModel() { // get side mesh var tr = transform.GetChild(0).GetChild(0).GetChild(0); var mf = tr.GetComponent<MeshFilter>(); if (!mf) { Debug.LogError("[StretchyConicTank] no model to reshape", part); return; } var m = mf.mesh; if (!m) { Debug.LogError("[StretchyConicTank] no mesh to reshape", part); return; } // prepare for building geometry if (circleSegments < 3) circleSegments = 3; if (heightSegments < 1) heightSegments = 1; int sideVerts = (circleSegments + 1) * (heightSegments + 1); int sideFaces = circleSegments * heightSegments * 2; int capVerts = circleSegments * 2; int capFaces = (circleSegments - 1) * 2; var dirs = new Vector3[circleSegments + 1]; for (int i = 0; i <= circleSegments; ++i) { float a = Mathf.PI * 2 * i / circleSegments; dirs[i] = new Vector3(Mathf.Cos(a), -Mathf.Sin(a), 0); } float baseRad = radialFactor * 1.25f; float topRad = topFactor * 1.25f; float height = stretchFactor * 1.875f; var slope = new BezierSlope(coneShape); var shape = new Vector3[heightSegments + 1]; for (int i = 0; i <= heightSegments; ++i) { float v = (float)i / heightSegments; Vector2 p; if (baseRad <= topRad) p = slope.interp(v); else { p = slope.interp(1 - v); p.y = 1 - p.y; } float y = (p.y - 0.5f) * height; float r = Mathf.Abs(baseRad - topRad) * p.x + Mathf.Min(baseRad, topRad); shape[i] = new Vector3(r, y, p.y); } // build side surface mesh m.Clear(); var verts = new Vector3[sideVerts]; var uv = new Vector2[sideVerts]; var norm = new Vector3[sideVerts]; var tang = new Vector4[sideVerts]; for (int i = 0, vi = 0; i <= heightSegments; ++i) { var p = shape[i]; Vector2 n; if (i == 0) n = shape[1] - shape[0]; else if (i == shape.Length - 1) n = shape[i] - shape[i - 1]; else n = shape[i + 1] - shape[i - 1]; n.Set(n.y, -n.x); n.Normalize(); for (int j = 0; j <= circleSegments; ++j, ++vi) { var d = dirs[j]; verts[vi] = d * p.x + Vector3.forward * p.y; norm[vi] = d * n.x + Vector3.forward * n.y; tang[vi].Set(-d.y, d.x, 0, 1); uv[vi].Set((float)j / circleSegments, p.z); } } // set vertex data to mesh m.vertices = verts; m.uv = uv; m.normals = norm; m.tangents = tang; m.uv2 = null; m.colors32 = null; var tri = new int[sideFaces * 3]; for (int i = 0, vi = 0, ti = 0; i < heightSegments; ++i, ++vi) for (int j = 0; j < circleSegments; ++j, ++vi) { int nv = vi + 1; tri[ti++] = vi; tri[ti++] = nv + circleSegments + 1; tri[ti++] = nv; tri[ti++] = vi; tri[ti++] = vi + circleSegments + 1; tri[ti++] = nv + circleSegments + 1; } m.triangles = tri; if (!HighLogic.LoadedSceneIsEditor) m.Optimize(); var collider = tr.GetComponent<MeshCollider>(); collider.sharedMesh = null; collider.sharedMesh = m; // get cap mesh tr = tr.GetChild(0); mf = tr.GetComponent<MeshFilter>(); if (!mf) { Debug.LogError("[StretchyConicTank] no model to reshape", part); return; } m = mf.mesh; if (!m) { Debug.LogError("[StretchyConicTank] no mesh to reshape", part); return; } // build cap mesh m.Clear(); verts = new Vector3[capVerts]; uv = new Vector2[capVerts]; norm = new Vector3[capVerts]; tang = new Vector4[capVerts]; const float capMapScale = 0.47f; for (int i = 0; i < circleSegments; ++i) { var d = dirs[i]; verts[i] = d * baseRad - Vector3.forward * height * 0.5f; norm[i] = -Vector3.forward; tang[i].Set(-1, 0, 0, 1); uv[i].Set(-d.x * capMapScale + 0.5f, d.y * capMapScale + 0.5f); verts[i + circleSegments] = d * topRad + Vector3.forward * height * 0.5f; norm[i + circleSegments] = Vector3.forward; tang[i + circleSegments].Set(1, 0, 0, 1); uv[i + circleSegments].Set(d.x * capMapScale + 0.5f, d.y * capMapScale + 0.5f); } // set vertex data to mesh m.vertices = verts; m.uv = uv; m.normals = norm; m.tangents = tang; m.uv2 = null; m.colors32 = null; tri = new int[capFaces * 3]; for (int i = 1, ti = 0; i < circleSegments; ++i, ti += 3) { int nv = i + 1; if (nv == circleSegments) nv = 0; tri[ti] = 0; tri[ti + 1] = i; tri[ti + 2] = nv; tri[ti + (circleSegments - 1) * 3] = circleSegments; tri[ti + 1 + (circleSegments - 1) * 3] = circleSegments + nv; tri[ti + 2 + (circleSegments - 1) * 3] = circleSegments + i; } m.triangles = tri; if (!HighLogic.LoadedSceneIsEditor) m.Optimize(); }