Fixed a few rotation bugs in flexible objects.

This commit is contained in:
leo 2016-04-19 16:30:29 +00:00
parent 8de6f06113
commit 6547969d24
3 changed files with 83 additions and 39 deletions

View file

@ -79,12 +79,11 @@ lcSynthInfo::lcSynthInfo(lcSynthType Type, float Length, int NumSections)
break;
}
mStart.Transform = lcMatrix44Identity();
mStart.Transform[1][1] = -1.0f;
mStart.Transform = lcMatrix44(lcMatrix33(lcVector3(0.0f, 0.0f, 1.0f), lcVector3(1.0f, 0.0f, 0.0f), lcVector3(0.0f, 1.0f, 0.0f)), lcVector3(0.0f, 0.0f, 0.0f));
mStart.Length = EdgeSectionLength;
mMiddle.Transform = lcMatrix44Identity();
mMiddle.Length = MidSectionLength;
mEnd.Transform = lcMatrix44Identity();
mEnd.Transform = lcMatrix44(lcMatrix33(lcVector3(0.0f, 0.0f, 1.0f), lcVector3(1.0f, 0.0f, 0.0f), lcVector3(0.0f, 1.0f, 0.0f)), lcVector3(0.0f, 0.0f, 0.0f));
mEnd.Length = EdgeSectionLength;
}
@ -109,16 +108,60 @@ void lcSynthInfo::GetDefaultControlPoints(lcArray<lcPieceControlPoint>& ControlP
break;
}
lcMatrix33 RotationY = lcMatrix33RotationY(LC_PI / 2.0f);
float HalfLength = mLength / 2.0f;
Scale = lcMin(Scale, HalfLength);
ControlPoints[0].Transform = lcMatrix44(RotationY, lcVector3(-HalfLength, 0.0f, 0.0f));
ControlPoints[0].Transform = lcMatrix44Translation(lcVector3(-HalfLength, 0.0f, 0.0f));
ControlPoints[0].Scale = Scale;
ControlPoints[1].Transform = lcMatrix44(RotationY, lcVector3( HalfLength, 0.0f, 0.0f));
ControlPoints[1].Transform = lcMatrix44Translation(lcVector3( HalfLength, 0.0f, 0.0f));
ControlPoints[1].Scale = Scale;
}
float lcSynthInfo::GetSectionTwist(const lcMatrix44& StartTransform, const lcMatrix44& EndTransform) const
{
lcVector3 StartTangent(StartTransform[1].x, StartTransform[1].y, StartTransform[1].z);
lcVector3 EndTangent(EndTransform[1].x, EndTransform[1].y, EndTransform[1].z);
lcVector3 StartUp(StartTransform[2].x, StartTransform[2].y, StartTransform[2].z);
lcVector3 EndUp(EndTransform[2].x, EndTransform[2].y, EndTransform[2].z);
float TangentDot = lcDot(StartTangent, EndTangent);
float UpDot = lcDot(StartUp, EndUp);
if (TangentDot > 0.99f && UpDot > 0.99f)
return 0.0f;
if (fabs(TangentDot) > 0.99f)
{
return acosf(lcClamp(lcDot(EndUp, StartUp), -1.0f, 1.0f));
}
else if (TangentDot > -0.99f)
{
lcVector3 Axis = lcCross(StartTangent, EndTangent);
float Angle = acosf(lcClamp(TangentDot, -1.0f, 1.0f));
lcMatrix33 Rotation = lcMatrix33FromAxisAngle(Axis, Angle);
lcVector3 AdjustedStartUp = lcMul(StartUp, Rotation);
return acosf(lcClamp(lcDot(EndUp, AdjustedStartUp), -1.0f, 1.0f));
}
lcVector3 StartSide(StartTransform[0].x, StartTransform[0].y, StartTransform[0].z);
lcVector3 EndSide(EndTransform[0].x, EndTransform[0].y, EndTransform[0].z);
float SideDot = lcDot(StartSide, EndSide);
if (fabs(SideDot) < 0.99f)
{
lcVector3 Axis = lcCross(StartSide, EndSide);
float Angle = acosf(SideDot);
lcMatrix33 Rotation = lcMatrix33FromAxisAngle(Axis, Angle);
lcVector3 AdjustedStartUp = lcMul(StartUp, Rotation);
return acosf(lcClamp(lcDot(EndUp, AdjustedStartUp), -1.0f, 1.0f));
}
return 0.0f;
}
void lcSynthInfo::CalculateSections(const lcArray<lcPieceControlPoint>& ControlPoints, lcArray<lcMatrix44>& Sections, void (*SectionCallback)(const lcVector3& CurvePoint, int SegmentIndex, float t, void* Param), void* CallbackParam) const
{
float SectionLength = 0.0f;
@ -129,7 +172,7 @@ void lcSynthInfo::CalculateSections(const lcArray<lcPieceControlPoint>& ControlP
lcMatrix44 StartTransform = lcMatrix44LeoCADToLDraw(ControlPoints[ControlPointIdx].Transform);
lcMatrix44 EndTransform = lcMatrix44LeoCADToLDraw(ControlPoints[ControlPointIdx + 1].Transform);
StartTransform = lcMatrix44(lcMul(lcMatrix33(StartTransform), lcMatrix33(mStart.Transform)), StartTransform.GetTranslation());
StartTransform = lcMatrix44(lcMul(lcMul(lcMatrix33(mStart.Transform), lcMatrix33(StartTransform)), lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f))), StartTransform.GetTranslation());
if (ControlPointIdx == 0)
{
@ -143,10 +186,8 @@ void lcSynthInfo::CalculateSections(const lcArray<lcPieceControlPoint>& ControlP
Sections.Add(StartTransform);
}
else
StartTransform = lcMatrix44(lcMul(lcMatrix33(StartTransform), lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f))), StartTransform.GetTranslation());
EndTransform = lcMatrix44(lcMul(lcMatrix33(EndTransform), lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f))), EndTransform.GetTranslation());
EndTransform = lcMatrix44(lcMul(lcMul(lcMatrix33(mEnd.Transform), lcMatrix33(EndTransform)), lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f))), EndTransform.GetTranslation());
SegmentControlPoints[0] = StartTransform.GetTranslation();
SegmentControlPoints[1] = lcMul31(lcVector3(0.0f, ControlPoints[ControlPointIdx].Scale, 0.0f), StartTransform);
@ -166,27 +207,19 @@ void lcSynthInfo::CalculateSections(const lcArray<lcPieceControlPoint>& ControlP
CurvePoints.Add(Position);
}
int CurrentPointIndex = 0;
lcVector3 StartUp(lcMul30(lcVector3(1.0f, 0.0f, 0.0f), StartTransform));
lcVector3 EndUp(lcMul30(lcVector3(1.0f, 0.0f, 0.0f), EndTransform));
lcVector4 UpRotation;
float UpDot = lcDot(StartUp, EndUp);
if (UpDot < 0.99f)
UpRotation = lcVector4(lcCross(StartUp, EndUp), acosf(UpDot));
else
UpRotation = lcVector4(0.0f, 0.0f, 0.0f, 0.0f);
float CurrentSegmentLength = 0.0f;
float TotalSegmentLength = 0.0f;
for (int PointIdx = 0; PointIdx < CurvePoints.GetSize() - 1; PointIdx++)
TotalSegmentLength += lcLength(CurvePoints[PointIdx] - CurvePoints[PointIdx + 1]);
lcVector3 StartUp(lcMul30(lcVector3(1.0f, 0.0f, 0.0f), StartTransform));
float Twist = GetSectionTwist(StartTransform, EndTransform);
int CurrentPointIndex = 0;
while (CurrentPointIndex < CurvePoints.GetSize() - 1)
{
float Length = lcLength(CurvePoints[CurrentPointIndex] - CurvePoints[CurrentPointIndex + 1]);
float Length = lcLength(CurvePoints[CurrentPointIndex + 1] - CurvePoints[CurrentPointIndex]);
CurrentSegmentLength += Length;
SectionLength -= Length;
CurrentPointIndex++;
@ -197,12 +230,22 @@ void lcSynthInfo::CalculateSections(const lcArray<lcPieceControlPoint>& ControlP
float t = (float)CurrentPointIndex / (float)(NumCurvePoints - 1);
float it = 1.0f - t;
lcVector3 Tangent = -3.0f * it * it * SegmentControlPoints[0] + (3.0f * it * it - 6.0f * t * it) * SegmentControlPoints[1] + (-3.0f * t * t + 6.0f * t * it) * SegmentControlPoints[2] + 3.0f * t * t * SegmentControlPoints[3];
lcVector3 Up = lcMul(StartUp, lcMatrix33FromAxisAngle(lcVector3(UpRotation[0], UpRotation[1], UpRotation[2]), UpRotation[3] * (CurrentSegmentLength / TotalSegmentLength)));
lcVector3 Side = lcCross(Tangent, Up);
Up = lcCross(Side, Tangent);
lcVector3 Tangent = lcNormalize(-3.0f * it * it * SegmentControlPoints[0] + (3.0f * it * it - 6.0f * t * it) * SegmentControlPoints[1] + (-3.0f * t * t + 6.0f * t * it) * SegmentControlPoints[2] + 3.0f * t * t * SegmentControlPoints[3]);
lcVector3 Up;
Sections.Add(lcMatrix44(lcMatrix33(lcNormalize(Up), lcNormalize(Tangent), lcNormalize(Side)), CurvePoints[CurrentPointIndex]));
if (Twist)
{
Up = lcMul(StartUp, lcMatrix33FromAxisAngle(Tangent, Twist * (CurrentSegmentLength / TotalSegmentLength)));
CurrentSegmentLength = 0.0f;
}
else
Up = StartUp;
lcVector3 Side = lcNormalize(lcCross(Tangent, Up));
Up = lcNormalize(lcCross(Side, Tangent));
StartUp = Up;
Sections.Add(lcMatrix44(lcMatrix33(Up, Tangent, Side), CurvePoints[CurrentPointIndex]));
if (SectionCallback)
SectionCallback(CurvePoints[CurrentPointIndex], ControlPointIdx, t, CallbackParam);
@ -219,7 +262,7 @@ void lcSynthInfo::CalculateSections(const lcArray<lcPieceControlPoint>& ControlP
while (Sections.GetSize() < mNumSections + 2)
{
lcMatrix44 EndTransform = lcMatrix44LeoCADToLDraw(ControlPoints[ControlPoints.GetSize() - 1].Transform);
EndTransform = lcMatrix44(lcMul(lcMatrix33(EndTransform), lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f))), EndTransform.GetTranslation());
EndTransform = lcMatrix44(lcMul(lcMul(lcMatrix33(mEnd.Transform), lcMatrix33(EndTransform)), lcMatrix33Scale(lcVector3(1.0f, -1.0f, 1.0f))), EndTransform.GetTranslation());
lcVector3 Position = lcMul31(lcVector3(0.0f, SectionLength, 0.0f), EndTransform);
EndTransform.SetTranslation(Position);
Sections.Add(EndTransform);

View file

@ -29,6 +29,7 @@ public:
lcMesh* CreateMesh(const lcArray<lcPieceControlPoint>& ControlPoints) const;
protected:
float GetSectionTwist(const lcMatrix44& StartTransform, const lcMatrix44& EndTransform) const;
void CalculateSections(const lcArray<lcPieceControlPoint>& ControlPoints, lcArray<lcMatrix44>& Sections, void(*SectionCallback)(const lcVector3& CurvePoint, int SegmentIndex, float t, void* Param), void* CallbackParam) const;
void AddRibbedHoseParts(lcMemFile& File, const lcArray<lcMatrix44>& Sections) const;
void AddFlexibleAxleParts(lcMemFile& File, lcLibraryMeshData& MeshData, const lcArray<lcMatrix44>& Sections) const;

View file

@ -775,8 +775,8 @@ void View::DrawSelectMoveOverlay()
lcVector3 Verts[38];
int NumVerts = 0;
Verts[NumVerts++] = lcVector3(0.0f, 0.0f, Length - OverlayScaleRadius);
Verts[NumVerts++] = lcVector3(0.0f, 0.0f, OverlayScaleRadius - Length);
Verts[NumVerts++] = lcVector3(Length - OverlayScaleRadius, 0.0f, 0.0f);
Verts[NumVerts++] = lcVector3(OverlayScaleRadius - Length, 0.0f, 0.0f);
float SinTable[9], CosTable[9];
@ -791,8 +791,8 @@ void View::DrawSelectMoveOverlay()
float x = CosTable[Step];
float y = SinTable[Step];
Verts[NumVerts++] = lcVector3(x * OverlayScaleInnerRadius, 0.0f, y * OverlayScaleInnerRadius + Length);
Verts[NumVerts++] = lcVector3(x * OverlayScaleRadius, 0.0f, y * OverlayScaleRadius + Length);
Verts[NumVerts++] = lcVector3(Length + x * OverlayScaleInnerRadius, 0.0f, y * OverlayScaleInnerRadius);
Verts[NumVerts++] = lcVector3(Length + x * OverlayScaleRadius, 0.0f, y * OverlayScaleRadius);
}
for (int Step = 0; Step <= 8; Step++)
@ -800,8 +800,8 @@ void View::DrawSelectMoveOverlay()
float x = CosTable[Step];
float y = SinTable[Step];
Verts[NumVerts++] = lcVector3(x * OverlayScaleInnerRadius, 0.0f, y * OverlayScaleInnerRadius - Length);
Verts[NumVerts++] = lcVector3(x * OverlayScaleRadius, 0.0f, y * OverlayScaleRadius - Length);
Verts[NumVerts++] = lcVector3(-Length + x * OverlayScaleInnerRadius, 0.0f, y * OverlayScaleInnerRadius);
Verts[NumVerts++] = lcVector3(-Length + x * OverlayScaleRadius, 0.0f, y * OverlayScaleRadius);
}
if (mTrackTool == LC_TRACKTOOL_SCALE_PLUS || mTrackTool == LC_TRACKTOOL_SCALE_MINUS)
@ -1812,7 +1812,7 @@ void View::UpdateTrackTool()
const float ScaleStart = (2.0f - OverlayScaleRadius) * OverlayScale + Strength;
const float ScaleEnd = (2.0f + OverlayScaleRadius) * OverlayScale + Strength;
if (AxisIndex == 0 && fabs(Proj1) < OverlayScaleRadius * OverlayScale)
if (AxisIndex == 1 && fabs(Proj1) < OverlayScaleRadius * OverlayScale)
{
if (Proj2 > ScaleStart && Proj2 < ScaleEnd)
{
@ -1827,7 +1827,7 @@ void View::UpdateTrackTool()
ClosestIntersectionDistance = IntersectionDistance;
}
}
else if (AxisIndex == 1 && fabs(Proj2) < OverlayScaleRadius * OverlayScale)
else if (AxisIndex == 2 && fabs(Proj2) < OverlayScaleRadius * OverlayScale)
{
if (Proj1 > ScaleStart && Proj1 < ScaleEnd)
{
@ -2592,9 +2592,9 @@ void View::OnMouseMove()
{
lcVector3 Direction;
if (mTrackTool == LC_TRACKTOOL_SCALE_PLUS)
Direction = lcVector3(0.0f, 0.0f, 1.0f);
Direction = lcVector3(1.0f, 0.0f, 0.0f);
else
Direction = lcVector3(0.0f, 0.0f, -1.0f);
Direction = lcVector3(-1.0f, 0.0f, 0.0f);
Direction = lcMul(Direction, RelativeRotation);