public static Node[] MatchNodeCount(Node[] from, Node[] to, Spline fromSpline) { int fromCount = from.Length; int toCount = to.Length; int difference = toCount - fromCount; List <Node> tempNodeList = new List <Node>(from); if (fromCount != toCount) { for (int i = 0; i < difference; i++) { //Adds Node between last and before last spline SplineNode lastNode = fromSpline.nodes[fromCount - 1]; SplineNode formerLastNode = fromSpline.nodes[fromCount - 2]; SplineNode firstNode = fromSpline.nodes[0]; float fullDist = Vector3.Distance(lastNode.Position, firstNode.Position); float formerDist = Vector3.Distance(formerLastNode.Position, firstNode.Position); float lastFormerDist = Vector3.Distance(formerLastNode.Position, lastNode.Position); float insertTime = ((lastFormerDist / 2) + formerDist) / fullDist; CurveSample insertNodeSample = GetSampleAt(fromSpline, insertTime); Node insertNode = new Node(insertNodeSample.location, insertNodeSample.tangent * 0.1f + insertNodeSample.location); tempNodeList.Insert(tempNodeList.Count - 1, insertNode); fromSpline.InsertNode(fromSpline.nodes.Count - 1, new SplineNode(insertNode.position, insertNode.handleOut)); } } Node[] insertedNodeArray = tempNodeList.ToArray(); return(insertedNodeArray); }
public static Spline MatchNodeCount(Spline from, Node[] to) { int fromCount = from.nodes.Count; int toCount = to.Length; int difference = toCount - fromCount; if (fromCount != toCount) { for (int i = 0; i < difference; i++) { //Adds Node between last and before last spline SplineNode lastNode = from.nodes[fromCount - 1]; SplineNode formerLastNode = from.nodes[fromCount - 2]; SplineNode firstNode = from.nodes[0]; float fullDist = Vector3.Distance(lastNode.Position, firstNode.Position); float formerDist = Vector3.Distance(formerLastNode.Position, firstNode.Position); float lastFormerDist = Vector3.Distance(formerLastNode.Position, lastNode.Position); float insertTime = ((lastFormerDist / 2) + formerDist) / fullDist; CurveSample insertNode = GetSampleAt(from, insertTime); from.InsertNode(fromCount - 1, new SplineNode(insertNode.location, insertNode.tangent * 0.1f + insertNode.location)); } } return(from); }
private void ComputePoints() { m_Samples.Clear(); Length = 0; Vector3 previousPosition = GetLocation(0); for (float t = 0; t < 1; t += m_TStep) { CurveSample sample = new CurveSample(); sample.location = GetLocation(t); sample.tangent = GetTangent(t); Length += Vector3.Distance(previousPosition, sample.location); sample.distance = Length; previousPosition = sample.location; m_Samples.Add(sample); } CurveSample lastSample = new CurveSample(); lastSample.location = GetLocation(1); lastSample.tangent = GetTangent(1); Length += Vector3.Distance(previousPosition, lastSample.location); lastSample.distance = Length; m_Samples.Add(lastSample); }
//void Update() //{ // distance += Time.deltaTime / DurationInSecond; // if (currentSpline != null) // { // if (distance > currentSpline.nodes.Count - 1) // { // distance = 0; // // --- Beni - 11.20. // // spline[0] has the complete track, so this logic is unneseccary and // // causes a bug once the cart reaches the end of the track // // since at the end of spline[0] we should not go spline[1] // // but to the beggining of spline[0], since it has the complete track // //GetNextSpline(); // // --- END // } // } // PlaceFollower(); //} private void PlaceFollower() { if (currentSpline != null) { if (Follower != null) { //// --- Beni 11.28. //// Changed to match contruder //// But it doesn't work because the spline length changes after generation //rate += Time.deltaTime / DurationInSecond; //if (rate > 1) //{ // rate--; //} //CurveSample sample = currentSpline.GetSampleAtDistance(currentSpline.Length * rate); //// --- END //CurveSample sample = currentSpline.GetSample(rate); CurveSample sample = currentSpline.GetSampleAtDistance(distance); Follower.transform.localPosition = currentSpline.WorldPosition(sample.location); Follower.transform.localRotation = sample.Rotation; } } else { currentSpline = SplineManager.instance.GetSplineComponent(splineCount); } }
private CurveSample getCurvePointAtDistance(float d) { if (d < 0 || d > Length) { throw new ArgumentException("Distance must be positive and less than curve length. Length = " + Length + ", given distance was " + d); } CurveSample previous = samples[0]; CurveSample next = null; foreach (CurveSample cp in samples) { if (cp.distance >= d) { next = cp; break; } previous = cp; } if (next == null) { throw new Exception("Can't find curve samples."); } float t = next == previous ? 0 : (d - previous.distance) / (next.distance - previous.distance); CurveSample res = new CurveSample(); res.distance = d; res.location = Vector3.Lerp(previous.location, next.location, t); res.tangent = Vector3.Lerp(previous.tangent, next.tangent, t).normalized; return(res); }
public CurveSample NewIteration() { m_IterSampleIndex = 0; CurveSample sample = Iterate(); return(sample); }
private void UpdateTransformOnSpline(GameObject objectToUpdate, Spline spline, float positionTime) { CurveSample p = Util.GetSampleAt(spline, positionTime); UpdatePositionOnSpline(objectToUpdate, p.location); UpdateRotationOnSpline(objectToUpdate, 0f, p.tangent); }
private CurveSample CatmullRom(int i, float u) { var sample = new CurveSample(); //----------- // When u==0, just return the first point of the interval if (u <= 0) { sample.Pos = _controlPoints[i].pos; sample.Rot = _controlPoints[i].rot; sample.U = 0; return(sample); } //---------- // Position var p1 = _controlPoints[i].pos; var p0 = p1; if (i > 0) { p0 = _controlPoints[i].pos; } var p2 = _controlPoints[i + 1].pos; var p3 = p2; if (i + 2 < _controlPoints.Count) { p3 = _controlPoints[i + 2].pos; } var tens = speedMultiplier; var u2 = u * u; var u3 = u2 * u; sample.Pos = (-tens * u + 2 * tens * u2 - tens * u3) * p0 + (1 + (tens - 3) * u2 + (2 - tens) * u3) * p1 + (tens * u + (3 - 2 * tens) * u2 + (tens - 2) * u3) * p2 + (tens * u3 - tens * u2) * p3; //---------- // Rotation var t1 = _controlPoints[i]; var t2 = _controlPoints[i + 1]; sample.Rot = _prevPoint.Rot; // Keep the forward tangent to the curve var tg = (sample.Pos - _prevPoint.Pos); var up = Vector3.Cross(tg, Vector3.Lerp(t1.right, t2.right, u)); if ((up.magnitude > 0) && (tg.magnitude > 0)) { sample.Rot = Quaternion.LookRotation(tg, up); } sample.U = u; return(sample); }
private CurveSample getCurvePointAtDistance(float d) { d = Mathf.Clamp(d, 0, Length); CurveSample previous = m_Samples[0]; CurveSample next = m_Samples[m_StepCount - 1]; for (int i = 0; i < m_StepCount; i++) { CurveSample cp = m_Samples[i]; if (cp.distance >= d) { next = cp; break; } previous = cp; } if (next == null) { throw new Exception("Can't find curve samples."); } float t = next == previous ? 0 : (d - previous.distance) / (next.distance - previous.distance); CurveSample res = new CurveSample(); res.distance = d; res.location = Vector3.Lerp(previous.location, next.location, t); res.tangent = Vector3.Lerp(previous.tangent, next.tangent, t).normalized; return(res); }
/// <summary> /// Following spline progressively. /// </summary> void Update() { if (!_isOk) { return; } _posOnSpline += Time.deltaTime * (speedInUnitsPerSecond / _splineRef.Length); // Don't query for position outside curve bounds _posOnSpline = Mathf.Clamp(_posOnSpline, 0.0f, 1.0f); CurveSample sample = _splineRef.GetSampleAtDistance(_posOnSpline * _splineRef.Length); // Add Spline object position offset if (_splineParent) { transform.position = (_splineParent.rotation * sample.location) + _splineRef.transform.position; } else { transform.position = sample.location + _splineRef.transform.position; } if (gameObject.tag != "Projectile") { transform.rotation = sample.Rotation; } }
private void ComputePoints() { samples.Clear(); Length = 0; Vector3 previousPosition = GetLocation(0); for (float t = 0; t < 1; t += T_STEP) { CurveSample sample = new CurveSample(); sample.location = GetLocation(t); sample.tangent = GetTangent(t); Length += Vector3.Distance(previousPosition, sample.location); sample.distance = Length; previousPosition = sample.location; samples.Add(sample); } CurveSample lastSample = new CurveSample(); lastSample.location = GetLocation(1); lastSample.tangent = GetTangent(1); Length += Vector3.Distance(previousPosition, lastSample.location); lastSample.distance = Length; samples.Add(lastSample); if (Changed != null) { Changed.Invoke(); } }
private void UpdateLeafTransform(GameObject leaf, Spline spline, float position, float yRotation, float localScale) { CurveSample p = Util.GetSampleAt(spline, position); leaf.transform.position = p.location + transform.position; leaf.transform.rotation = Quaternion.Euler(0, yRotation, Vector3.Angle(Vector3.up, p.tangent)); leaf.transform.localScale = Vector3.one * localScale; }
private void PlaceFollower() { if (generated != null) { CurveSample sample = spline.GetSample(rate); generated.transform.localPosition = sample.location; } }
private CurveSample Hermite(int i, float u) { var sample = new CurveSample(); //----------- // When u==0, just return the first point of the interval if (u <= 0) { sample.Pos = _controlPoints[i].pos; sample.Rot = _controlPoints[i].rot; sample.U = 0; return(sample); } //---------- // Position var p0 = _controlPoints[i].pos; var p1 = _controlPoints[i + 1].pos; var v0 = _controlPoints[i].forward * speedMultiplier; var v1 = _controlPoints[i + 1].forward * speedMultiplier; var u2 = u * u; var u3 = u2 * u; sample.Pos = (1 - 3 * u2 + 2 * u3) * p0 + u2 * (3 - 2 * u) * p1 + u * (u - 1) * (u - 1) * v0 + u2 * (u - 1) * v1; //---------- // Rotation var t1 = _controlPoints[i]; var t2 = _controlPoints[i + 1]; sample.Rot = _prevPoint.Rot; // Keep the forward tangent to the curve var tg = (sample.Pos - _prevPoint.Pos); tg.Normalize(); var up = Vector3.Cross(tg, Vector3.Lerp(t1.right, t2.right, u)); //var up = Vector3.Cross(tg, t1.right); //Debug.Log(sample.Pos.x); if ((up.magnitude > 0) && (tg.magnitude > 0)) { sample.Rot = Quaternion.LookRotation(tg, up); } else { Debug.Log("error magnitude tg up"); } sample.U = u; return(sample); }
private void PlaceFollower() { if (m_Spline != null) { CurveSample sample = m_Spline.GetSample(rate); transform.localPosition = sample.location; transform.localRotation = sample.Rotation; } }
private void UpdateTransformOnSpline(GameObject objectToUpdate, Spline spline, float positionTime, float yEulerAngle, float localScale) { CurveSample p = Util.GetSampleAt(spline, positionTime); UpdatePositionOnSpline(objectToUpdate, p.location); UpdateRotationOnSpline(objectToUpdate, yEulerAngle, p.tangent); UpdateLocalScale(objectToUpdate, localScale); objectToUpdate.transform.RotateAround(transform.position, Vector3.up, _d.Rotation); }
void PFConstSpeed() { locationOnSpline += Time.deltaTime * speed; locationOnSpline %= spline.Length; CurveSample sample = spline.GetSampleAtDistance(locationOnSpline); follower.transform.position = sample.location; follower.transform.localRotation = sample.Rotation; }
public CurveSample Iterate() { if (m_IterSampleIndex >= m_StepCount) { return(null); } CurveSample sample = m_Samples[m_IterSampleIndex++]; return(sample); }
private CurveSample Lineal(int i, float u) { var sample = new CurveSample(); var t1 = _controlPoints[i]; var t2 = _controlPoints[i + 1]; sample.Pos = Vector3.Lerp(t1.pos, t2.pos, u); sample.Rot = Quaternion.Slerp(t1.rot, t2.rot, u); sample.U = u; return(sample); }
void PFZeroToOne() { float playerInput = controls.Player.Forward.ReadValue <float>() - controls.Player.Reverse.ReadValue <float>(); locationOnSpline = Mathf.Clamp(spline.Length, 0, 20) * playerInput; if (locationOnSpline < 0) { locationOnSpline += spline.Length; } CurveSample sample = spline.GetSampleAtDistance(locationOnSpline); follower.transform.position = sample.location; follower.transform.localRotation = sample.Rotation; }
void PFVelocityControl() { float playerInput = controls.Player.Forward.ReadValue <float>() - controls.Player.Reverse.ReadValue <float>(); locationOnSpline += playerInput * Time.deltaTime * speed; if (locationOnSpline < 0) { locationOnSpline += spline.Length; } locationOnSpline %= spline.Length; CurveSample sample = spline.GetSampleAtDistance(locationOnSpline); follower.transform.position = sample.location; follower.transform.localRotation = sample.Rotation; }
private void MoveFollower(float newDistanceAlongSpline) { if (spline == null || follower == null) { return; } CurveSample lengthSample = spline.GetSampleAtDistance(newDistanceAlongSpline); // CurveSample lengthSample = spline.GetSample(progress * (spline.nodes.Count - 1)); // For getting the sample weighted by nodes var transform = follower.transform; Vector3 localPosition = lengthSample.location; transform.localPosition = localPosition; transform.localRotation = lengthSample.Rotation; }
/// <summary> /// Instantiate the prefabs here /// </summary> public void Sow() { UOUtility.DestroyChildren(generated); UnityEngine.Random.InitState(randomSeed); if (spacing + spacingRange <= 0 || prefab == null) { return; } float distance = 0; while (distance <= spline.Length) { CurveSample sample = spline.GetSampleAtDistance(distance); GameObject go; go = Instantiate(prefab, generated.transform); go.transform.localRotation = Quaternion.identity; go.transform.localPosition = Vector3.zero; go.transform.localScale = Vector3.one; // move along spline, according to spacing + random go.transform.localPosition = sample.location; // apply scale + random float rangedScale = scale + UnityEngine.Random.Range(0, scaleRange); go.transform.localScale = new Vector3(rangedScale, rangedScale, rangedScale); // rotate with random yaw if (isRandomYaw) { go.transform.Rotate(0, 0, UnityEngine.Random.Range(-180, 180)); } else { go.transform.rotation = sample.Rotation; } // move orthogonaly to the spline, according to offset + random var binormal = (Quaternion.LookRotation(sample.tangent, sample.up) * Vector3.right).normalized; var localOffset = offset + UnityEngine.Random.Range(0, offsetRange * Math.Sign(offset)); localOffset *= sample.scale.x; binormal *= localOffset; go.transform.position += binormal; distance += spacing + UnityEngine.Random.Range(0, spacingRange); } }
// Place Objects void GenerateObjects() { // Keep generating objects until the end is reached while (count <= numNodes) { //move along the spline CurveSample sample = spline.GetSample(count); Vector3 splineLocalLocation = sample.location; //location tracked 2 parents up splineLocation = extruders[0].transform.TransformPoint(splineLocalLocation); splineRotation = sample.Rotation; //rotation tracked 1 parent up, camera being in same level but above splineTan = sample.tangent; splineUp = sample.up; Ring(splineLocation); //splineDir = spline.GetComponent<Spline>().GetSample(count).Direction; //Instantiate(item, splineLocation, splineRotation); count += .04f; } }
private void FixedUpdate() { if (!path.IsLoop) { /* * //Add or Subtract the spline position based on what direction we need the platform to move. If the timer is greater than the spline's length * //or less than 0, we change direction * if (!Back) Position += Time.fixedDeltaTime * speed; * else Position -= Time.fixedDeltaTime * speed; * if (Position >= 0.99f && !Back) * { * t = 1; * Back = true; * } * if (Position <= 0.01f && Back) Back = false; */ t = Mathf.PingPong(Time.time * speed, 1f); Position = Mathf.Lerp(0, 1, LinearMovementCurve.Evaluate(t)); } else { //If the spline path is a loop, we simply set the timer to 0 if it reaches the end. Position += Time.fixedDeltaTime * speed; if (Position >= 0.99f) { Position = 0; } } //Get the delta position CurrentPos = platform.position; if (PreviousPos != CurrentPos) { deltaPosition = CurrentPos - PreviousPos; PreviousPos = CurrentPos; } //Then we get the position we need on the spline based on the timer, and move the platform to it. //Since SplineMesh returns spline positions in local space, we need to use TransformPoint to get it in world space. CurveSample p_sample = path.GetSampleAtDistance(Position * Length); platform.MovePosition(transform.TransformPoint(p_sample.location)); }
//--METHODS public void PlaceOnSpline(Spline spline) { if (locationOnSpline.x < 0) { locationOnSpline.x += spline.Length; } locationOnSpline.x %= spline.Length; CurveSample sample = spline.GetSampleAtDistance(locationOnSpline.x); Vector3 location = sample.location + (transform.right * locationOnSpline.z) + (transform.up * locationOnSpline.y); if (useParentSpline) { transform.localPosition = location; transform.localRotation = sample.Rotation; } else { transform.position = location + spline.transform.position; transform.rotation = sample.Rotation; } }
private void FixedUpdate() { if (activeSpline != null) { //Get Sonic's current position along the spline CurveSample cur = activeSpline.GetSampleAtDistance(GetClosestPos(Player.rigidBody.position)); //Get the Right vector of the current spline position so we can accurately adjust Sonic's velocity Vector3 SplinePlane = Vector3.Cross(cur.tangent, cur.up); //Project the vector onto the plane Player.rigidBody.velocity = Vector3.ProjectOnPlane(Player.rigidBody.velocity, SplinePlane); //Project the input too Player.InputDir = Vector3.ProjectOnPlane(Player.InputDir, SplinePlane); //Set the Player's position along the spline plane Vector3 NewPos = activeSpline.transform.TransformPoint(cur.location); NewPos.y = Player.rigidBody.position.y; Debug.DrawLine(transform.position, NewPos); Player.rigidBody.position = Vector3.MoveTowards(Player.rigidBody.position, NewPos, 1f); } }
void Update() { if (!_isOk) { return; } _posOnSpline += Time.deltaTime * (speedInUnitsPerSecond / _splineRef.Length); // Don't query for position outside curve bounds _posOnSpline = Mathf.Clamp(_posOnSpline, 0.0f, 1.0f); CurveSample sample = _splineRef.GetSampleAtDistance(_posOnSpline * _splineRef.Length); // Add Spline object position offset transform.position = sample.location + _splineRef.transform.position; transform.rotation = sample.Rotation; // Reset if (Math.Abs(_posOnSpline - 1.0f) < 0.0001f) { _posOnSpline = 0.0f; } }
void DuplicateOP() { if (m_Spline != null & m_Prefab != null && m_Generated != null) { UOUtility.DestroyChildren(m_Generated); UnityEngine.Random.InitState(m_RandomSeed); if (m_Spacing + m_SpacingRange <= 0 || m_Prefab == null) { return; } float distance = 0; while (distance <= m_Spline.Length) { CurveSample sample = m_Spline.GetSampleAtDistance(distance); GameObject go; go = Instantiate(m_Prefab, m_Generated.transform); go.transform.localRotation = Quaternion.identity; go.transform.localPosition = Vector3.zero; go.transform.localScale = Vector3.one; // move along spline, according to spacing + random go.transform.localPosition = sample.location; // apply scale + random float rangedScale = m_Scale + UnityEngine.Random.Range(0, m_ScaleRange); go.transform.localScale = new Vector3(rangedScale, rangedScale, rangedScale); switch (m_RotationMode) { case (RotationMode.FollowSplineNormal): go.transform.rotation = sample.Rotation; break; case (RotationMode.CustomRotation): go.transform.Rotate(m_Rotation); break; case (RotationMode.Combined): go.transform.rotation = sample.Rotation; go.transform.rotation *= Quaternion.Euler(m_Rotation); break; } // // rotate with random yaw if (m_RandomizeRotation) { float RandomRange = UnityEngine.Random.Range(m_MinRange, m_MaxRange); go.transform.rotation *= Quaternion.Euler(RandomRange, RandomRange, RandomRange); } // move orthogonaly to the spline, according to offset + random Vector3 binormal = Vector3.zero; float localOffset = 1.0f; switch (m_OffsetAxiz) { case OffsetAxis.X: binormal = (Quaternion.LookRotation(sample.tangent, sample.up) * Vector3.right).normalized; localOffset = m_Offset + UnityEngine.Random.Range(0, m_OffsetRange * Math.Sign(m_Offset)); localOffset *= sample.scale.x; break; case OffsetAxis.Y: binormal = (Quaternion.LookRotation(sample.tangent, sample.up) * Vector3.up).normalized; localOffset = m_Offset + UnityEngine.Random.Range(m_OffsetRange * Math.Sign(m_Offset), 0); localOffset *= sample.scale.y; break; } binormal *= localOffset; go.transform.position += binormal; distance += m_Spacing + UnityEngine.Random.Range(0, m_SpacingRange); } } }
public override void Generate() { double tCurveLen = CurveUtils.ArcLength(Curve); SampledArcLengthParam pAxis = new SampledArcLengthParam(Axis, Axis.Length); double tAxisLen = pAxis.ArcLength; double tScale = tAxisLen / tCurveLen; int nRings = Curve.Length; int nRingSize = (NoSharedVertices) ? Slices + 1 : Slices; int nCapVertices = (NoSharedVertices) ? Slices + 1 : 1; if (Capped == false) { nCapVertices = 0; } vertices = new VectorArray3d(nRingSize * nRings + 2 * nCapVertices); uv = new VectorArray2f(vertices.Count); normals = new VectorArray3f(vertices.Count); int nSpanTris = (nRings - 1) * (2 * Slices); int nCapTris = (Capped) ? 2 * Slices : 0; triangles = new IndexArray3i(nSpanTris + nCapTris); float fDelta = (float)((Math.PI * 2.0) / Slices); double tCur = 0; CurveSample s = pAxis.Sample(tCur); Frame3f f0 = new Frame3f((Vector3F)s.position, (Vector3F)s.tangent, 1); Frame3f fCur = f0; // generate tube for (int ri = 0; ri < nRings; ++ri) { if (ri > 0) { tCur += (Curve[ri] - Curve[ri - 1]).Length; s = pAxis.Sample(tCur * tScale); fCur.Origin = (Vector3F)s.position; fCur.AlignAxis(1, (Vector3F)s.tangent); } Vector3D v_along = Curve[ri]; Vector3F v_frame = fCur.ToFrameP((Vector3F)v_along); float uv_along = (float)ri / (float)(nRings - 1); // generate vertices int nStartR = ri * nRingSize; for (int j = 0; j < nRingSize; ++j) { float angle = (float)j * fDelta; // [TODO] this is not efficient...use Matrix3f? Vector3F v_rot = Quaternionf.AxisAngleR(Vector3F.AxisY, angle) * v_frame; Vector3D v_new = fCur.FromFrameP(v_rot); int k = nStartR + j; vertices[k] = v_new; float uv_around = (float)j / (float)(nRingSize); uv[k] = new Vector2F(uv_along, uv_around); // [TODO] proper normal Vector3F n = (Vector3F)(v_new - fCur.Origin).Normalized; normals[k] = n; } } // generate triangles int ti = 0; for (int ri = 0; ri < nRings - 1; ++ri) { int r0 = ri * nRingSize; int r1 = r0 + nRingSize; for (int k = 0; k < nRingSize - 1; ++k) { triangles.Set(ti++, r0 + k, r0 + k + 1, r1 + k + 1, Clockwise); triangles.Set(ti++, r0 + k, r1 + k + 1, r1 + k, Clockwise); } if (NoSharedVertices == false) // close disc if we went all the way { triangles.Set(ti++, r1 - 1, r0, r1, Clockwise); triangles.Set(ti++, r1 - 1, r1, r1 + nRingSize - 1, Clockwise); } } if (Capped) { // find avg start loop size Vector3D vAvgStart = Vector3D.Zero, vAvgEnd = Vector3D.Zero; for (int k = 0; k < Slices; ++k) { vAvgStart += vertices[k]; vAvgEnd += vertices[(nRings - 1) * nRingSize + k]; } vAvgStart /= (double)Slices; vAvgEnd /= (double)Slices; Frame3f fStart = f0; fStart.Origin = (Vector3F)vAvgStart; Frame3f fEnd = fCur; fEnd.Origin = (Vector3F)vAvgEnd; // add endcap verts int nBottomC = nRings * nRingSize; vertices[nBottomC] = fStart.Origin; uv[nBottomC] = new Vector2F(0.5f, 0.5f); normals[nBottomC] = -fStart.Z; startCapCenterIndex = nBottomC; int nTopC = nBottomC + 1; vertices[nTopC] = fEnd.Origin; uv[nTopC] = new Vector2F(0.5f, 0.5f); normals[nTopC] = fEnd.Z; endCapCenterIndex = nTopC; if (NoSharedVertices) { // duplicate first loop and make a fan w/ bottom-center int nExistingB = 0; int nStartB = nTopC + 1; for (int k = 0; k < Slices; ++k) { vertices[nStartB + k] = vertices[nExistingB + k]; //uv[nStartB + k] = (Vector2f)Polygon.Vertices[k].Normalized; float angle = (float)k * fDelta; double cosa = Math.Cos(angle), sina = Math.Sin(angle); uv[nStartB + k] = new Vector2F(0.5f * (1.0f + cosa), 0.5f * (1 + sina)); normals[nStartB + k] = normals[nBottomC]; } append_disc(Slices, nBottomC, nStartB, true, Clockwise, ref ti); // duplicate second loop and make fan int nExistingT = nRingSize * (nRings - 1); int nStartT = nStartB + Slices; for (int k = 0; k < Slices; ++k) { vertices[nStartT + k] = vertices[nExistingT + k]; //uv[nStartT + k] = (Vector2f)Polygon.Vertices[k].Normalized; float angle = (float)k * fDelta; double cosa = Math.Cos(angle), sina = Math.Sin(angle); uv[nStartT + k] = new Vector2F(0.5f * (1.0f + cosa), 0.5f * (1 + sina)); normals[nStartT + k] = normals[nTopC]; } append_disc(Slices, nTopC, nStartT, true, !Clockwise, ref ti); } else { append_disc(Slices, nBottomC, 0, true, Clockwise, ref ti); append_disc(Slices, nTopC, nRingSize * (nRings - 1), true, !Clockwise, ref ti); } } }