You can download all C# source files with solutions to exercises here:
http://hectorsoft.com/bwaszak_com/MIGS2017_SolutionsToExercises.zip
using UnityEngine;
using System.Collections;
public class Exercise_1_Solution
{
// Hints:
// You will need to use dot and cross products.
// "PointToTest" is already lying on a plane with a triangle.
public static bool IsPointInsideTriangle(Vector3 A, Vector3 B, Vector3 C, Vector3 TriangleNormal, Vector3 PointToTest)
{
Vector3 edge0 = B - A;
Vector3 cross0 = Vector3.Cross(edge0, PointToTest - A);
if (Vector3.Dot(cross0, TriangleNormal) < 0.0f)
return false;
Vector3 edge1 = C - B;
Vector3 cross1 = Vector3.Cross(edge1, PointToTest - B);
if (Vector3.Dot(cross1, TriangleNormal) < 0.0f)
return false;
Vector3 edge2 = A - C;
Vector3 cross2 = Vector3.Cross(edge2, PointToTest - C);
if (Vector3.Dot(cross2, TriangleNormal) < 0.0f)
return false;
return true;
}
}
public class Exercise_2_Solution
{
// Hints:
// You will need to use dot product and vector operations (like normalization, distance comparison).
public static Vector3 CalculateNearestPointOnCurve(Vector3[] CurvePoints, Vector3 PointToTest)
{
Vector3 Result = Vector3.zero;
float nearestDistanceSqr = float.MaxValue;
for (int i=0 ; i<(CurvePoints.Length-1) ; ++i)
{
Vector3 CurveDir = CurvePoints[i+1] - CurvePoints[i];
Vector3 CurveDirNormalized = CurveDir.normalized;
Vector3 vP = PointToTest - CurvePoints[i];
float dotValue = Vector3.Dot(CurveDirNormalized, vP);
Vector3 PointOnCurve = dotValue * CurveDirNormalized;
PointOnCurve += CurvePoints[i];
if (dotValue < 0.0f)
{
PointOnCurve = CurvePoints[i];
}
else if (dotValue > CurveDir.magnitude)
{
PointOnCurve = CurvePoints[i+1];
}
float currentDistanceSqr = (PointToTest - PointOnCurve).sqrMagnitude;
if (currentDistanceSqr < nearestDistanceSqr)
{
Result = PointOnCurve;
nearestDistanceSqr = currentDistanceSqr;
}
}
return Result;
}
}
public class Exercise_3_Solution
{
// Hints:
//
// Rotation matrix around x-axis:
// [ 1, 0, 0, 0 ]
// [ 0, cosA, -sinA, 0 ]
// [ 0, sinA, cosA, 0 ]
// [ 0, 0, 0, 1 ]
//
// Rotation matrix around y-axis:
// [ cosA, 0, sinA, 0 ]
// [ 0, 1, 0, 0 ]
// [ -sinA, 0, cosA, 0 ]
// [ 0, 0, 0, 1 ]
private static Matrix4x4 RotationMatrixAroundX(float AngleX)
{
Matrix4x4 m = Matrix4x4.identity;
m.m11 = Mathf.Cos(AngleX);
m.m12 = -Mathf.Sin(AngleX);
m.m21 = Mathf.Sin(AngleX);
m.m22 = Mathf.Cos(AngleX);
return m;
}
private static Matrix4x4 RotationMatrixAroundY(float AngleY)
{
Matrix4x4 m = Matrix4x4.identity;
m.m00 = Mathf.Cos(AngleY);
m.m02 = Mathf.Sin(AngleY);
m.m20 = -Mathf.Sin(AngleY);
m.m22 = Mathf.Cos(AngleY);
return m;
}
public static Matrix4x4 AddRotationsFromAngles(Matrix4x4 BaseTransform, float AngleX, float AngleY)
{
return RotationMatrixAroundX(AngleX) * RotationMatrixAroundY(AngleY) * BaseTransform;
}
}
public class Exercise_4_Solution
{
public static Quaternion CalculateShortestRotationBetweenTwoOrientations(
Quaternion PreviousOrientation, Quaternion NewOrientation)
{
Quaternion q = NewOrientation;
if (Quaternion.Dot(PreviousOrientation, NewOrientation) < 0.0f)
{
q = new Quaternion(-NewOrientation.x, -NewOrientation.y, -NewOrientation.z, -NewOrientation.w);
}
Quaternion qDifference = q * Quaternion.Inverse(PreviousOrientation);
return qDifference;
}
}
public class Exercise_5_Solution
{
// Useful hints:
//
// Vector3(0.0f, 1.0f, 0.0f) ---> Local rotation axis for arms to be used in this exercise.
// sin( Angle_in_Radians ) ---> Mathf.Sin( Angle_in_Radians );
// Time ---> Time.timeSinceLevelLoad;
public static void ProceduralAnimation(
Transform LeftArm,
Transform LeftForearm,
Transform RightArm,
Transform RightForearm)
{
float t0 = 0.4f * Time.timeSinceLevelLoad;
float t1 = t0 - Mathf.Floor(t0);
float sinValue = Mathf.Sin(2.0f * Mathf.PI * t1);
float angleLeftArm = 40.0f * sinValue;
LeftArm.localRotation = Quaternion.AngleAxis(angleLeftArm, new Vector3(0.0f, 1.0f, 0.0f));
float angleLeftForearm = 38.0f * (1.0f + sinValue);
LeftForearm.localRotation = Quaternion.AngleAxis(angleLeftForearm, new Vector3(0.0f, 1.0f, 0.0f));
float angleRightArm = 40.0f * sinValue;
RightArm.localRotation = Quaternion.AngleAxis(angleRightArm, new Vector3(0.0f, 1.0f, 0.0f));
float angleRightForearm = 38.0f * (1.0f + sinValue);
RightForearm.localRotation = Quaternion.AngleAxis(angleRightForearm, new Vector3(0.0f, 1.0f, 0.0f));
}
}