public static Vector3 operator *(Quaternion xform, Vector3 vec) { /* From nVidia SDK */ Vector3 uv, uuv; Vector3 qvec = new Vector3(xform.X, xform.Y, xform.Z); uv = qvec.Cross(vec); uuv = qvec.Cross(uv); uv *= (2.0f * xform.W); uuv *= 2.0f; return vec + uv + uuv; }
/// <summary> /// Initializes a new instance of the <see cref="Quaternion"/> class. /// </summary> /// <param name="sourcePosition">The source position.</param> /// <param name="destinationPosition">The destination position.</param> public Quaternion(Vector3 sourcePosition, Vector3 destinationPosition) { var r = sourcePosition.Cross(destinationPosition); var s = Functions.Sqrt(2 * (1 + sourcePosition.Dot(destinationPosition))); mValues = new Vector4(r / s, s / 2); }
public void Cross() { var vector1 = new Vector3(2.0f, 3.0f, 4.0f); var vector2 = new Vector3(5.0f, 6.0f, 7.0f); var cross = vector1.Cross(vector2); Assert.AreEqual(-3.0f, cross.X); Assert.AreEqual(6.0f, cross.Y); Assert.AreEqual(-3.0f, cross.Z); }
/// <summary> /// 2つのベクトルがなす角をかえす /// </summary> /// <param name="vecA"></param> /// <param name="vecB"></param> /// <returns></returns> public static double VecToRad( Vector3 vecA, Vector3 vecB ) { vecA.Normalize(); vecB.Normalize(); double dir = (double)(Axiom.Math.Utility.ASin(vecA.Dot(vecB)) - Axiom.Math.Utility.HALF_PI); Vector3 resVec = vecA.Cross(vecB); if (resVec.z < 0) dir = -dir; return dir; }
public MeshTriangle(byte id, Vector3 p0, Vector3 p1, Vector3 p2) { Id = id; P0 = p0; P1 = p1; P2 = p2; Points = new List<Vector3>{P0, P1, P2}; U = P1 - P0; V = P2 - P0; Normal = U.Cross(V).NormalizeRet(); Direction = CalculateDirection(); UU = U.Dot(U); VV = V.Dot(V); UV = U.Dot(V); D = UV * UV - UU * VV; }
public void ProjectionMesh(Transform meshTransform, Mesh mesh, Ray ray, float radius, Material material) { //Debug Code Start float startTime = Time.realtimeSinceStartup; //Debug Code Stop Vector3[] meshVertices = mesh.vertices; int newVertices = 0; int[] newTriangles = new int[meshVertices.Length]; for (int i = 0, j = 0; i < meshVertices.Length; i += 3) { Vector3 v0 = meshTransform.TransformPoint(meshVertices[i]); Vector3 v1 = meshTransform.TransformPoint(meshVertices[i + 1]); Vector3 v2 = meshTransform.TransformPoint(meshVertices[i + 2]); if (RayTriangleIntersection(ray, v0, v1, v2, radius)) { newTriangles[j] = i; newTriangles[j + 1] = i + 1; newTriangles[j + 2] = i + 2; j += 3; } newVertices = j; } Vector3[] vertices = new Vector3[newVertices]; Vector2[] uv = new Vector2[newVertices]; int[] triangles = new int[newVertices]; Vector3 x = Vector3.Cross(ray.direction, meshVertices[0]).normalized; Vector3 y = Vector3.Cross(ray.direction, x).normalized; Vector2 offset = new Vector2(Vector3.Dot(ray.origin, -x), Vector3.Dot(ray.origin, -y)) * 0.5f / radius + Vector2.one * 0.5f; for (int i = 0; i < vertices.Length; i++) { vertices[i] = meshVertices[newTriangles[i]]; Vector3 v = meshTransform.TransformPoint(vertices[i]); uv[i] = new Vector2(Vector3.Dot(v, x), Vector3.Dot(v, y)) * 0.5f / radius + offset; triangles[i] = i; } Mesh newMesh = new Mesh(); newMesh.Clear(); newMesh.vertices = vertices; newMesh.uv = uv; newMesh.normals = new Vector3[triangles.Length]; newMesh.triangles = triangles; newMesh.RecalculateNormals(); GameObject newGameObject = new GameObject(); newGameObject.AddComponent <MeshFilter>(); newGameObject.AddComponent <MeshRenderer>(); newGameObject.GetComponent <MeshFilter>().mesh = newMesh; newGameObject.GetComponent <MeshRenderer>().material = material; newGameObject.transform.name = material.name + " Projection"; newGameObject.transform.parent = meshTransform; newGameObject.transform.localPosition = Vector3.zero; newGameObject.transform.localRotation = Quaternion.identity; newGameObject.transform.localScale = Vector3.one; //Debug Code Start print("ProjectionMesh total execution time: " + (Time.realtimeSinceStartup - startTime) + " seconds for " + (newMesh.triangles.Length / 3) + " triangles"); //Debug Code Stop }
/// <summary> /// Returns the closest distance to the given ray from a point. /// </summary> /// <param name="ray">The ray.</param> /// <param name="point">The point to check distance from the ray.</param> /// <returns>Squared distance from the point to the closest point of the ray.</returns> public static float SqrDistanceToRay(Ray ray, Vector3 point) { return(Vector3.Cross(ray.direction, point - ray.origin).sqrMagnitude); }
public static Matrix3 LookAt(Vector3 forward, Vector3 up) { var Z = forward.Normalize(); var X = up.Cross(Z).Normalize(); var Y = Z.Cross(X); return new Matrix3(X, Y, Z); }
void ForceFling() { Transform flinger; Rigidbody flung; Vector3 dir; Transform activeLink; if (partnerNum == 0) { flinger = partnerRB[0].transform; flung = partnerRB[1]; vibrationJoystick.Rumble(1, 1f, 0.2f); activeLink = links[10]; } else { partnerNum = 1; flinger = partnerRB[1].transform; flung = partnerRB[0]; vibrationJoystick.Rumble(0, 1f, 0.2f); activeLink = links[2]; } /* ============ New way of handling direction ============ */ //if (useNewFlingDirection) //{ Vector3 a = flinger.position - flung.position; // flung -> flinger Vector3 b = midLink.transform.position - flung.position; // flung -> midlink Debug.DrawRay(flung.position, a, Color.green, 1f); Debug.DrawRay(flung.position, b, Color.red, 1f); // Rotation axis Vector3 axis = Vector3.Cross(a, b).normalized; // Direction of fling float angle = Vector3.Angle(a, b); // If the angle is too small, increase it if (angle < 20f) { angle = flingDirectionAngleCurve.Evaluate(angle); } dir = b; Quaternion rot = Quaternion.AngleAxis(angle, axis); dir = (rot * dir).normalized; Debug.DrawRay(flung.position, dir * 4f, Color.magenta, 1f, false); //} //else //{ // // ============ Old way of handling direction ============ */ // if (activeLink.position.y > (flung.transform.position.y + 0.15f) && partnerDistance > ropeLength) // dir = ((activeLink.position - flung.transform.position).normalized + Vector3.up).normalized; // //otherwise, set the direction to be the direction between the two players // else // dir = (activeLink.position - flung.transform.position).normalized; //} float distance = Vector3.Distance(links[6].transform.position, flung.transform.position); float forceMagnitude = tugCurve.Evaluate(distance); forceMagnitude *= flingModifier; if (forceMagnitude > 650f) { OnPerfectFlingVisualsAndSound(1 - partnerNum); if (!PhotonNetwork.OfflineMode) { photonView.RPC("OnPerfectFlingVisualsAndSound", RpcTarget.Others, 1 - partnerNum); } } //float forceMagnitude = 8f * pullConstant * distance; //Clamp the force so it's magnitude never exceeds a maximum force, //which is determined by the maximum length that the rope can be stretched //forceMagnitude = Mathf.Clamp(forceMagnitude, 0f, 4f * 6f * pullConstant); forceToBeApplied = dir * forceMagnitude; //if (forceMagnitude>500f) StartCoroutine(PlayFlingTrail(1 - partnerNum, forceMagnitude)); if (!PhotonNetwork.OfflineMode) { photonView.RPC("PlayFlingTrailRPC", RpcTarget.Others, 1 - partnerNum, forceMagnitude); } ApplyTugArrow(flung.transform, dir, forceMagnitude); FlingPlayerRB(1 - partnerNum, forceToBeApplied); /*if (PhotonNetwork.OfflineMode || flung.GetComponent<PhotonView>().IsMine) { * flung.AddForce(forceToBeApplied, ForceMode.Acceleration); * } * else { * FlingPlayerRigidbody(partnerNum, forceToBeApplied); * flung.AddForce(forceToBeApplied, ForceMode.Acceleration); * }*/ //Debug.LogWarning("Distance: " + distance + ", Force: " + forceMagnitude); //Debug.Log("New Link Based Tug Force: " + forceMagnitude); //Debug.Log(currLength); //Debug.DrawRay(partner.transform.position, dir, Color.cyan, 0.3f); }
/// <summary> /// Concatenates two quaternions. The right argument is applied first. /// </summary> /// <param name="left">The left operand which is applied after the right one.</param> /// <param name="right">The right operand which is applied first.</param> /// <returns>A quaternion containing the rotations of both given quaternions.</returns> public static Quaternion operator *(Quaternion left, Quaternion right) { var v1 = new Vector3(right.X, right.Y, right.Z); var v2 = new Vector3(left.X, left.Y, left.Z); var w = left.W * right.W - v1.Dot(v2); var v = right.W * v2 + left.W * v1 + v2.Cross(v1); return new Quaternion(v, w); }
// HANDLING TOUCH INPUT HERE void LateUpdate() { if (overUI && !controlsInUse) { return; } var canvasScale = app.scaleFactorRefCanvas.scaleFactor; #if UNITY_EDITOR // test on iPhone 5c //canvasScale = 1.893333f; #endif //Debug.LogWarning("CANVAS SCALE: "+canvasScale); var mltpl = Time.deltaTime * 35f / canvasScale; if (hasTouches()) { stopFlying(); Vector2 touch1Pos = getTouchPos(); if (touchCount() == 1 && !Input.GetKey(KeyCode.LeftCommand)) { // moving firstTouchInRotateMode = true; if (firstTouchInMoveMode) { Ray ray = Camera.main.ScreenPointToRay(touch1Pos); RaycastHit hit; int buildingLayer = 1 << 9 | 1 << 10 | 1 << 11 | 1 << 12 | 1 << 13 | 1 << 14; if (Physics.Raycast(ray.origin, ray.direction, out hit, Mathf.Infinity, buildingLayer)) { worldInteractPoint = hit.point; firstTouchInMoveMode = false; touch1StartPos = touch1Pos; } } else { var touchDelta = touch1Pos - touch1StartPos; if (touchDelta.magnitude > 0.5f) { controlsInUse = true; } var camToPointDist = (Camera.main.transform.position - worldInteractPoint).magnitude; var h1 = 1f; //Camera.main.nearClipPlane; var h2 = camToPointDist - h1; var worldDelta = touchDelta / h1 * h2; var cameraForwardDirection = (Camera.main.transform.forward - new Vector3(0, Camera.main.transform.forward.y, 0)).normalized; var cameraRightDirection = (Camera.main.transform.right - new Vector3(0, Camera.main.transform.right.y, 0)).normalized; if (canMove) { Camera.main.transform.position -= (cameraForwardDirection * worldDelta.y * mltpl * moveSpeed + cameraRightDirection * worldDelta.x * mltpl * moveSpeed); } touch1StartPos = touch1Pos; } } else if (touchCount() == 2 || !touchInput() && Input.GetKey(KeyCode.LeftCommand)) { // rotating firstTouchInMoveMode = true; if (firstTouchInRotateMode) { touch1StartPos = touch1Pos; if (touchInput()) { touch2StartPos = getTouch2Pos(); } var startCenterPoint = (touch1StartPos + touch2StartPos) / 2f; Ray ray = Camera.main.ScreenPointToRay(startCenterPoint); RaycastHit hit; int buildingLayer = 1 << 9 | 1 << 10 | 1 << 11 | 1 << 12 | 1 << 13 | 1 << 14; if (Physics.Raycast(ray.origin, ray.direction, out hit, Mathf.Infinity, buildingLayer)) { worldInteractPoint = hit.point; firstTouchInRotateMode = false; } } else { if (touchInput()) { // rotate and zoom camera with 2 fingers Vector2 touch2Pos = getTouch2Pos(); var deltaDistance = (touch2Pos - touch1Pos).magnitude - (touch2StartPos - touch1StartPos).magnitude; var startCenterPoint = (touch1StartPos + touch2StartPos) / 2f; var startVector = touch1StartPos - touch2StartPos; var currentCenterPoint = (touch1Pos + touch2Pos) / 2f; var currentVector = touch1Pos - touch2Pos; // get signed vector var deltaDegrees = Vector2.Angle(currentVector, startVector); if (Mathf.Abs(deltaDegrees) > 1f) { controlsInUse = true; } Vector3 cross = Vector3.Cross(currentVector, startVector); if (cross.z > 0) { deltaDegrees *= -1; } var deltaY = currentCenterPoint.y - startCenterPoint.y; if (touchRotatePhiZoomMode || touchRotateThetaMode || touchRotatePhiZoomMode) { if (touchRotateThetaMode) { var deltaTheta = deltaY * rotateThetaSpeed * mltpl; Camera.main.transform.RotateAround(worldInteractPoint, Camera.main.transform.right, deltaTheta); } else if (touchRotatePhiZoomMode) { var deltaPhi = deltaDegrees * rotatePhiSpeed /**mltpl*/; var oldPos = Camera.main.transform.position; Camera.main.transform.RotateAround(worldInteractPoint, Vector3.up, deltaPhi); var heightCoeff = (Camera.main.transform.position.y - minHeight) / (maxHeight - minHeight); if (heightCoeff < 0.1f) { heightCoeff = 0.1f; } var deltaZoom = deltaDistance * zoomSpeed * mltpl * heightCoeff; var translation = (worldInteractPoint - Camera.main.transform.position).normalized * deltaZoom; Camera.main.transform.Translate(translation, Space.World); // check if camera too close to worldInteractPoint, and revert changes if too close var pos_after_translate = Camera.main.transform.position; var dst_to_interact_point = (worldInteractPoint - pos_after_translate).magnitude; //Debug.LogWarning ("DST to interact point: "+dst_to_interact_point); if (dst_to_interact_point < 3f) { Camera.main.transform.position = oldCamPos; Camera.main.transform.rotation = oldCamRot; } } else { } } else { if (Mathf.Abs(deltaY) > touchRotateThetaThreshold) { touchRotateThetaMode = true; } else if (Mathf.Abs(deltaDegrees) > touchRotatePhiThreshold || Mathf.Abs(deltaDistance) > touchZoomThreshold) { touchRotatePhiZoomMode = true; } else { } } touch1StartPos = touch1Pos; touch2StartPos = touch2Pos; } } } } else { controlsInUse = false; firstTouchInMoveMode = true; firstTouchInRotateMode = true; touchRotatePhiZoomMode = false; touchRotateThetaMode = false; } // check camera borders var newPos = Camera.main.transform.position; var newRot = Camera.main.transform.rotation.eulerAngles; var thetaAngle = AngleSigned(Camera.main.transform.up, Vector3.up, -Camera.main.transform.right); // borders if (!flying) { if (newPos.y < minHeight || newPos.y > maxHeight || thetaAngle < minAngle || thetaAngle > maxAngle) { Camera.main.transform.position = oldCamPos; Camera.main.transform.rotation = oldCamRot; } else { oldCamPos = Camera.main.transform.position; oldCamRot = Camera.main.transform.rotation; } } }
public static Matrix LookAtRH(Vector3 eye, Vector3 at, Vector3 up) { var result = new Matrix(); Vector3 vectorNormal = (at - eye).Normal; Vector3 right = up.Cross(vectorNormal); Vector3 rightNormal = right.Normal; Vector3 upNormal = vectorNormal.Cross(right).Normal; result[0, 0] = -rightNormal.X; result[1, 0] = -rightNormal.Y; result[2, 0] = -rightNormal.Z; result[3, 0] = rightNormal.Dot(eye); result[0, 1] = upNormal.X; result[1, 1] = upNormal.Y; result[2, 1] = upNormal.Z; result[3, 1] = -upNormal.Dot(eye); result[0, 2] = -vectorNormal.X; result[1, 2] = -vectorNormal.Y; result[2, 2] = -vectorNormal.Z; result[3, 2] = vectorNormal.Dot(eye); result[0, 3] = 0.0f; result[1, 3] = 0.0f; result[2, 3] = 0.0f; result[3, 3] = 1.0f; return result; }
public void Render(Vector3[] points, Vector3[] directions, bool circle) { int stepsAmount = 0; Line[] lines = new Line[circle ? points.Length : points.Length - 1]; for (int i = 0; i < lines.Length; i++) { int i2 = (i + 1) % points.Length; lines[i] = new Line(new Vector2(points[i].x, points[i].z), new Vector2(points[i2].x, points[i2].z)); } List <Vector3> vertices = new List <Vector3>(); List <Vector2> uvs = new List <Vector2>(); List <int> triangles = new List <int>(); float angle = 0f; if (points.Length >= 4) { for (int i = 0; i < points.Length; i++) { Vector3 toRight; if (circle) { Vector3 nextPoint = points[(i + 1) % points.Length]; Vector3 prevPoint = points[i - 1 < 0 ? points.Length - 1 : i - 1]; toRight = (nextPoint - prevPoint).normalized; angle = 0f;// Vector3.Angle(points[i] - prevPoint, nextPoint - points[i]); for (int j = -2; j <= 2; j++) { int prevJ = (j + i - 1) < 0 ? (points.Length + (j + i - 1)) : ((j + i - 1) % points.Length); int nextJ = (j + i + 1) < 0 ? (points.Length + (j + i + 1)) : ((j + i + 1) % points.Length); int atJ = (j + i) < 0 ? (points.Length + (j + i)) : ((j + i) % points.Length); float angleHere = Vector3.Angle(points[atJ] - points[prevJ], points[nextJ] - points[atJ]); float factor = 0f; if (Mathf.Abs(j) == 2) { factor = 0.06f; } else if (Mathf.Abs(j) == 1) { factor = 0.23f; } else { factor = 0.42f; } angle += (angleHere * factor); } Vector2 forward = new Vector2(points[i].x - prevPoint.x, points[i].z - prevPoint.z); Ray2D rayF = new Ray2D(new Vector2(prevPoint.x, prevPoint.z), forward); if ((Utils.PointRightTo(rayF, new Vector2(nextPoint.x, nextPoint.z))) == (Vector2.Angle(new Vector2(-directions[i].z, directions[i].x), rayF.direction) >= 90f)) { angle = 0f; } } else { if (i == 0) { toRight = (points[i + 1] - points[0]).normalized; } else if (i == points.Length - 1) { toRight = (points[points.Length - 1] - points[points.Length - 2]).normalized; } else { Vector3 nextPoint = points[i + 1]; Vector3 prevPoint = points[i - 1]; toRight = (nextPoint - prevPoint).normalized; } } Vector3 down = Vector3.Cross(toRight, directions[i]).normalized; if (down.y > 0f) { down *= -1f; } float minDistance = float.MaxValue; int lineIndex = -1; Line thisLine = new Line(new Vector2(points[i].x + directions[i].normalized.x * 0.05f, points[i].z + directions[i].normalized.z * 0.05f), new Vector2(points[i].x + directions[i].normalized.x, points[i].z + directions[i].normalized.z)); for (int j = 0; j < lines.Length; j++) { int j1 = j == 0 ? lines.Length - 1 : j - 1; int j2 = (j + 1) % lines.Length; Vector2 intersectPoint; if (j1 != i && j != i && j2 != i && lines[i].Intersects(thisLine, out intersectPoint)) { if (Vector2.Distance(intersectPoint, new Vector2(points[i].x, points[i].z)) < minDistance) { minDistance = Vector2.Distance(intersectPoint, new Vector2(points[i].x, points[i].z)); lineIndex = j; } } } if (lineIndex != -1) { if (minDistance < 0.1f) { minDistance = 0.1f; } int lineIndex2 = (lineIndex + 1) % points.Length; Vector3 lowestPoint = points[lineIndex]; if (lowestPoint.y > points[lineIndex2].y) { lowestPoint = points[lineIndex2]; } directions[i] = new Vector3(directions[i].normalized.x, (lowestPoint.y - points[i].y) * (1f / minDistance), directions[i].normalized.z); } uvs.Add(new Vector2(points[i].x, points[i].z)); vertices.Add(points[i]); int counter = 0; float x = 0f; while (stepsAmount == 0 ? x < maxDistance : counter < stepsAmount) { float[] func = fallFunction(angleResolution * counter); x = func[0]; Vector3 vert = points[i] + directions[i].normalized * func[0] * Mathf.Min((1f / (angle / 4.5f)), 1f) + down * func[1]; //vertices.Add(new Vector3(vert.x, (GeneratedTrack.GetTensorHeight(vert) - 1.2f) * (x / maxDistance) + ((maxDistance - x) / maxDistance) * vert.y, vert.z)); vertices.Add(new Vector3(vert.x, (GeneratedTrack.GetTensorHeight(vert)) + (x / maxDistance) * -1.2f, vert.z)); uvs.Add(new Vector2(vertices[vertices.Count - 1].x, vertices[vertices.Count - 1].z)); counter++; } if (stepsAmount == 0) { stepsAmount = counter; } if (i > 0) { for (int j = 0; j < stepsAmount - 1; j++) { if (Vector3.Cross((vertices[vertices.Count - (j + 1)] - vertices[vertices.Count - (j + 1 + stepsAmount + 1)]), (vertices[vertices.Count - (j + 1 + stepsAmount + 1)] - vertices[vertices.Count - (j + 2 + stepsAmount + 1)])).y > 0f) { triangles.Add(vertices.Count - (j + 1 + stepsAmount + 1)); triangles.Add(vertices.Count - (j + 2 + stepsAmount + 1)); triangles.Add(vertices.Count - (j + 1)); } else { triangles.Add(vertices.Count - (j + 1 + stepsAmount + 1)); triangles.Add(vertices.Count - (j + 1)); triangles.Add(vertices.Count - (j + 2 + stepsAmount + 1)); } if (Vector3.Cross((vertices[vertices.Count - (j + 2)] - vertices[vertices.Count - (j + 1)]), (vertices[vertices.Count - (j + 1)] - vertices[vertices.Count - (j + 2 + stepsAmount + 1)])).y > 0f) { triangles.Add(vertices.Count - (j + 1)); triangles.Add(vertices.Count - (j + 2 + stepsAmount + 1)); triangles.Add(vertices.Count - (j + 2)); } else { triangles.Add(vertices.Count - (j + 1)); triangles.Add(vertices.Count - (j + 2)); triangles.Add(vertices.Count - (j + 2 + stepsAmount + 1)); } } } if (i == points.Length - 1 && circle) { for (int j = 0; j < stepsAmount - 1; j++) { if (Vector3.Cross((vertices[stepsAmount - (j + 1)] - vertices[vertices.Count - (j + 1)]), (vertices[vertices.Count - (j + 1)] - vertices[vertices.Count - (j + 2)])).y > 0f) { triangles.Add(vertices.Count - (j + 1)); triangles.Add(vertices.Count - (j + 2)); triangles.Add(stepsAmount - (j + 1)); } else { triangles.Add(vertices.Count - (j + 1)); triangles.Add(stepsAmount - (j + 1)); triangles.Add(vertices.Count - (j + 2)); } if (Vector3.Cross((vertices[stepsAmount - (j + 2)] - vertices[stepsAmount - (j + 1)]), (vertices[stepsAmount - (j + 1)] - vertices[vertices.Count - (j + 2)])).y > 0f) { triangles.Add(stepsAmount - (j + 1)); triangles.Add(vertices.Count - (j + 2)); triangles.Add(stepsAmount - (j + 2)); } else { triangles.Add(stepsAmount - (j + 1)); triangles.Add(stepsAmount - (j + 2)); triangles.Add(vertices.Count - (j + 2)); } } } } GetComponent <MeshFilter>().mesh.Clear(); GetComponent <MeshFilter>().mesh.vertices = vertices.ToArray(); for (int i = 0; i < uvs.Count; i++) { //uvs[i] = uvs[i] / 15f; } GetComponent <MeshFilter>().mesh.uv = uvs.ToArray(); GetComponent <MeshFilter>().mesh.subMeshCount = 1; GetComponent <MeshFilter>().mesh.SetTriangles(triangles.ToArray(), 0); GetComponent <MeshFilter>().mesh.RecalculateNormals(); GetComponent <MeshCollider>().sharedMesh = GetComponent <MeshFilter>().mesh; } }
//Modified Tube-generation algorithm from http://wiki.unity3d.com/index.php/ProceduralPrimitives //closedTube: If true, ignores startRadian & endRadian and creates a regular closed tube. If false, creates an open tube segment ranging from startRadian to endRadian. public static GameObject generateTube(float innerRadiusBottom, float outerRadiusBottom, float innerRadiusTop, float outerRadiusTop, float height, float startRadian, float endRadian, int sides, bool closedTube) { GameObject result = new GameObject(); MeshFilter filter = result.AddComponent <MeshFilter>(); MeshRenderer mr = result.AddComponent <MeshRenderer>(); Mesh mesh = filter.mesh; mesh.Clear(); if (closedTube) { startRadian = 0f; endRadian = Mathf.PI * 2f; } int nbVerticesCap = sides * 2 + 2; int nbVerticesSides = sides * 2 + 2; #region Vertices // bottom + top + sides + segment caps int nbVertOpenTube = nbVerticesCap * 2 + nbVerticesSides * 2 + 8; int nbVertClosedTube = nbVerticesCap * 2 + nbVerticesSides * 2; Vector3[] vertices; if (closedTube) { vertices = new Vector3[nbVertClosedTube]; } else { vertices = new Vector3[nbVertOpenTube]; } int vert = 0; // Bottom cap int sideCounter = 0; while (vert < nbVerticesCap) { if (sideCounter == sides && closedTube) { sideCounter = 0; } float r1 = startRadian + ((float)(sideCounter++) / sides * (endRadian - startRadian)); float cos = Mathf.Cos(r1); float sin = Mathf.Sin(r1); vertices[vert] = new Vector3(cos * (innerRadiusBottom), 0f, sin * (innerRadiusBottom)); vertices[vert + 1] = new Vector3(cos * (outerRadiusBottom), 0f, sin * (outerRadiusBottom)); vert += 2; } // Top cap sideCounter = 0; while (vert < nbVerticesCap * 2) { if (sideCounter == sides && closedTube) { sideCounter = 0; } float r1 = startRadian + ((float)(sideCounter++) / sides * (endRadian - startRadian)); float cos = Mathf.Cos(r1); float sin = Mathf.Sin(r1); vertices[vert] = new Vector3(cos * (innerRadiusTop), height, sin * (innerRadiusTop)); vertices[vert + 1] = new Vector3(cos * (outerRadiusTop), height, sin * (outerRadiusTop)); vert += 2; } // Sides (out) sideCounter = 0; while (vert < nbVerticesCap * 2 + nbVerticesSides) { if (sideCounter == sides && closedTube) { sideCounter = 0; } float r1 = startRadian + ((float)(sideCounter++) / sides * (endRadian - startRadian)); float cos = Mathf.Cos(r1); float sin = Mathf.Sin(r1); vertices[vert] = new Vector3(cos * (outerRadiusTop), height, sin * (outerRadiusTop)); vertices[vert + 1] = new Vector3(cos * (outerRadiusBottom), 0, sin * (outerRadiusBottom)); vert += 2; } // Sides (in) sideCounter = 0; while (vert < nbVertClosedTube) { if (sideCounter == sides && closedTube) { sideCounter = 0; } float r1 = startRadian + ((float)(sideCounter++) / sides * (endRadian - startRadian)); float cos = Mathf.Cos(r1); float sin = Mathf.Sin(r1); vertices[vert] = new Vector3(cos * (innerRadiusTop), height, sin * (innerRadiusTop)); vertices[vert + 1] = new Vector3(cos * (innerRadiusBottom), 0, sin * (innerRadiusBottom)); vert += 2; } // Open segments if (!closedTube) { vertices[vert++] = vertices[0]; vertices[vert++] = vertices[1]; vertices[vert++] = vertices[nbVerticesCap]; vertices[vert++] = vertices[nbVerticesCap + 1]; vertices[vert++] = vertices[nbVerticesCap - 2]; vertices[vert++] = vertices[nbVerticesCap - 1]; vertices[vert++] = vertices[2 * nbVerticesCap - 2]; vertices[vert] = vertices[2 * nbVerticesCap - 1]; } #endregion #region Normales // bottom + top + sides Vector3[] normales = new Vector3[vertices.Length]; vert = 0; // Bottom cap while (vert < nbVerticesCap) { normales[vert++] = Vector3.down; } // Top cap while (vert < nbVerticesCap * 2) { normales[vert++] = Vector3.up; } // Sides (out) sideCounter = 0; while (vert < nbVerticesCap * 2 + nbVerticesSides) { if (sideCounter == sides && closedTube) { sideCounter = 0; } float r1 = startRadian + ((float)(sideCounter++) / sides * (endRadian - startRadian)); normales[vert] = new Vector3(Mathf.Cos(r1), 0f, Mathf.Sin(r1)); normales[vert + 1] = normales[vert]; vert += 2; } // Sides (in) sideCounter = 0; while (vert < nbVertClosedTube) { if (sideCounter == sides && closedTube) { sideCounter = 0; } float r1 = startRadian + ((float)(sideCounter++) / sides * (endRadian - startRadian)); normales[vert] = -(new Vector3(Mathf.Cos(r1), 0f, Mathf.Sin(r1))); normales[vert + 1] = normales[vert]; vert += 2; } // Open segments if (!closedTube) { Vector3 vecA = vertices[nbVertOpenTube - 7] - vertices[nbVertOpenTube - 8]; Vector3 vecB = vertices[nbVertOpenTube - 6] - vertices[nbVertOpenTube - 8]; Vector3 normal = Vector3.Cross(vecB, vecA); normal = Vector3.Normalize(normal); normales[vert++] = normal; normales[vert++] = normal; normales[vert++] = normal; normales[vert++] = normal; vecA = vertices[nbVertOpenTube - 4] - vertices[nbVertOpenTube - 3]; vecB = vertices[nbVertOpenTube - 1] - vertices[nbVertOpenTube - 3]; normal = Vector3.Cross(vecB, vecA); normal = Vector3.Normalize(normal); normales[vert++] = normal; normales[vert++] = normal; normales[vert++] = normal; normales[vert] = normal; } #endregion #region UVs Vector2[] uvs = new Vector2[vertices.Length]; vert = 0; // Bottom cap sideCounter = 0; while (vert < nbVerticesCap) { float t = (float)(sideCounter++) / sides; uvs[vert++] = new Vector2(0f, t); uvs[vert++] = new Vector2(1f, t); } // Top cap sideCounter = 0; while (vert < nbVerticesCap * 2) { float t = (float)(sideCounter++) / sides; uvs[vert++] = new Vector2(0f, t); uvs[vert++] = new Vector2(1f, t); } // Sides (out) sideCounter = 0; while (vert < nbVerticesCap * 2 + nbVerticesSides) { float t = (float)(sideCounter++) / sides; uvs[vert++] = new Vector2(t, 0f); uvs[vert++] = new Vector2(t, 1f); } // Sides (in) sideCounter = 0; while (vert < nbVertClosedTube) { float t = (float)(sideCounter++) / sides; uvs[vert++] = new Vector2(t, 0f); uvs[vert++] = new Vector2(t, 1f); } // Open segments if (!closedTube) { uvs[vert++] = new Vector2(0, 0); uvs[vert++] = new Vector2(0, 1); uvs[vert++] = new Vector2(1, 0); uvs[vert++] = new Vector2(1, 1); uvs[vert++] = new Vector2(0, 1); uvs[vert++] = new Vector2(0, 0); uvs[vert++] = new Vector2(1, 1); uvs[vert] = new Vector2(1, 0); } #endregion #region Triangles int nbFace = sides * 4; if (!closedTube) { nbFace += 2; } int nbTriangles = nbFace * 2; int nbIndexes = nbTriangles * 3; int[] triangles = new int[nbIndexes]; // Bottom cap int i = 0; sideCounter = 0; while (sideCounter < sides) { int current = sideCounter * 2; int next = sideCounter * 2 + 2; triangles[i++] = next + 1; triangles[i++] = next; triangles[i++] = current; triangles[i++] = current + 1; triangles[i++] = next + 1; triangles[i++] = current; sideCounter++; } // Top cap while (sideCounter < sides * 2) { int current = sideCounter * 2 + 2; int next = sideCounter * 2 + 4; triangles[i++] = current; triangles[i++] = next; triangles[i++] = next + 1; triangles[i++] = current; triangles[i++] = next + 1; triangles[i++] = current + 1; sideCounter++; } // Sides (out) while (sideCounter < sides * 3) { int current = sideCounter * 2 + 4; int next = sideCounter * 2 + 6; triangles[i++] = current; triangles[i++] = next; triangles[i++] = next + 1; triangles[i++] = current; triangles[i++] = next + 1; triangles[i++] = current + 1; sideCounter++; } // Sides (in) while (sideCounter < sides * 4) { int current = sideCounter * 2 + 6; int next = sideCounter * 2 + 8; triangles[i++] = next + 1; triangles[i++] = next; triangles[i++] = current; triangles[i++] = current + 1; triangles[i++] = next + 1; triangles[i++] = current; sideCounter++; } // Segment Caps if (!closedTube) { triangles[i++] = nbVertOpenTube - 5; triangles[i++] = nbVertOpenTube - 7; triangles[i++] = nbVertOpenTube - 8; triangles[i++] = nbVertOpenTube - 5; triangles[i++] = nbVertOpenTube - 8; triangles[i++] = nbVertOpenTube - 6; triangles[i++] = nbVertOpenTube - 2; triangles[i++] = nbVertOpenTube - 4; triangles[i++] = nbVertOpenTube - 3; triangles[i++] = nbVertOpenTube - 2; triangles[i++] = nbVertOpenTube - 3; triangles[i++] = nbVertOpenTube - 1; } #endregion mesh.vertices = vertices; mesh.normals = normales; mesh.uv = uvs; mesh.triangles = triangles; mesh.RecalculateBounds(); return(result); }
public static bool IsTriTriIntersect(Tri tri1, Tri tri2) { var distanceTri1_2 = CheckDistances(tri1, tri2); if (distanceTri1_2 == DistanceType.NON_ZERO_SAME_SIGN) { return(false); } var distanceTri2_1 = CheckDistances(tri2, tri1); if (distanceTri2_1 == DistanceType.NON_ZERO_SAME_SIGN) { return(false); } if (distanceTri1_2 == DistanceType.ZERO || distanceTri2_1 == DistanceType.ZERO) { return(IsCoplanarIntersect(tri1, tri2)); } var L_intersectLine = Vector3.Cross(tri1.normal, tri2.normal); var max = Math.Abs(L_intersectLine.X); var index = 0; var bb = Math.Abs(L_intersectLine.Y); var cc = Math.Abs(L_intersectLine.Z); if (bb > max) { max = bb; index = 1; } if (cc > max) { max = cc; index = 2; } float vp0, vp1, vp2, up0, up1, up2; vp0 = tri1.v0.ElemByIndex(index); vp1 = tri1.v1.ElemByIndex(index); vp2 = tri1.v2.ElemByIndex(index); up0 = tri2.v0.ElemByIndex(index); up1 = tri2.v1.ElemByIndex(index); up2 = tri2.v2.ElemByIndex(index); // compute interval for triangle 1 float a = 0, b = 0, c = 0, x0 = 0, x1 = 0; float dv0 = Vector3.Dot(tri2.normal, tri1.v0) + tri2.d; float dv1 = Vector3.Dot(tri2.normal, tri1.v1) + tri2.d; float dv2 = Vector3.Dot(tri2.normal, tri1.v2) + tri2.d; float dv0dv1 = dv0 * dv1; float dv0dv2 = dv0 * dv2; if (ComputeIntervals(vp0, vp1, vp2, dv0, dv1, dv2, dv0dv1, dv0dv2, ref a, ref b, ref c, ref x0, ref x1)) { return(false); //return TriTriCoplanar(n1, v0, v1, v2, u0, u1, u2); } // compute interval for triangle 1 float du0 = Vector3.Dot(tri1.normal, tri2.v0) + tri1.d; float du1 = Vector3.Dot(tri1.normal, tri2.v1) + tri1.d; float du2 = Vector3.Dot(tri1.normal, tri2.v2) + tri1.d; float du0du1 = du0 * du1; float du0du2 = du0 * du2; // compute interval for triangle 2 float d = 0, e = 0, f = 0, y0 = 0, y1 = 0; if (ComputeIntervals(up0, up1, up2, du0, du1, du2, du0du1, du0du2, ref d, ref e, ref f, ref y0, ref y1)) { return(false); //return TriTriCoplanar(n1, v0, v1, v2, u0, u1, u2); } float xx, yy, xxyy, tmp; xx = x0 * x1; yy = y0 * y1; xxyy = xx * yy; tmp = a * xxyy; Vector2 isect1 = Vector2.Zero, isect2 = Vector2.Zero; isect1.X = tmp + b * x1 * yy; isect1.Y = tmp + c * x0 * yy; tmp = d * xxyy; isect2.X = tmp + e * xx * y1; isect2.Y = tmp + f * xx * y0; Sort(isect1); Sort(isect2); return(!(isect1.Y < isect2.X || isect2.Y < isect1.X)); }
/// <summary> /// Method to curve text along a Unity animation curve. /// </summary> /// <param name="textComponent"></param> /// <returns></returns> IEnumerator WarpText() { VertexCurve.preWrapMode = WrapMode.Clamp; VertexCurve.postWrapMode = WrapMode.Clamp; //Mesh mesh = m_TextComponent.textInfo.meshInfo[0].mesh; Vector3[] vertices; Matrix4x4 matrix; m_TextComponent.havePropertiesChanged = true; // Need to force the TextMeshPro Object to be updated. CurveScale *= 10; float old_CurveScale = CurveScale; float old_ShearValue = ShearAmount; AnimationCurve old_curve = CopyAnimationCurve(VertexCurve); while (true) { if (!m_TextComponent.havePropertiesChanged && old_CurveScale == CurveScale && old_curve.keys[1].value == VertexCurve.keys[1].value && old_ShearValue == ShearAmount) { yield return(null); continue; } old_CurveScale = CurveScale; old_curve = CopyAnimationCurve(VertexCurve); old_ShearValue = ShearAmount; m_TextComponent.ForceMeshUpdate(); // Generate the mesh and populate the textInfo with data we can use and manipulate. TMP_TextInfo textInfo = m_TextComponent.textInfo; int characterCount = textInfo.characterCount; if (characterCount == 0) { continue; } //vertices = textInfo.meshInfo[0].vertices; //int lastVertexIndex = textInfo.characterInfo[characterCount - 1].vertexIndex; float boundsMinX = m_TextComponent.bounds.min.x; //textInfo.meshInfo[0].mesh.bounds.min.x; float boundsMaxX = m_TextComponent.bounds.max.x; //textInfo.meshInfo[0].mesh.bounds.max.x; for (int i = 0; i < characterCount; i++) { if (!textInfo.characterInfo[i].isVisible) { continue; } int vertexIndex = textInfo.characterInfo[i].vertexIndex; // Get the index of the mesh used by this character. int materialIndex = textInfo.characterInfo[i].materialReferenceIndex; vertices = textInfo.meshInfo[materialIndex].vertices; // Compute the baseline mid point for each character Vector3 offsetToMidBaseline = new Vector2((vertices[vertexIndex + 0].x + vertices[vertexIndex + 2].x) / 2, textInfo.characterInfo[i].baseLine); //float offsetY = VertexCurve.Evaluate((float)i / characterCount + loopCount / 50f); // Random.Range(-0.25f, 0.25f); // Apply offset to adjust our pivot point. vertices[vertexIndex + 0] += -offsetToMidBaseline; vertices[vertexIndex + 1] += -offsetToMidBaseline; vertices[vertexIndex + 2] += -offsetToMidBaseline; vertices[vertexIndex + 3] += -offsetToMidBaseline; // Apply the Shearing FX float shear_value = ShearAmount * 0.01f; Vector3 topShear = new Vector3(shear_value * (textInfo.characterInfo[i].topRight.y - textInfo.characterInfo[i].baseLine), 0, 0); Vector3 bottomShear = new Vector3(shear_value * (textInfo.characterInfo[i].baseLine - textInfo.characterInfo[i].bottomRight.y), 0, 0); vertices[vertexIndex + 0] += -bottomShear; vertices[vertexIndex + 1] += topShear; vertices[vertexIndex + 2] += topShear; vertices[vertexIndex + 3] += -bottomShear; // Compute the angle of rotation for each character based on the animation curve float x0 = (offsetToMidBaseline.x - boundsMinX) / (boundsMaxX - boundsMinX); // Character's position relative to the bounds of the mesh. float x1 = x0 + 0.0001f; float y0 = VertexCurve.Evaluate(x0) * CurveScale; float y1 = VertexCurve.Evaluate(x1) * CurveScale; Vector3 horizontal = new Vector3(1, 0, 0); //Vector3 normal = new Vector3(-(y1 - y0), (x1 * (boundsMaxX - boundsMinX) + boundsMinX) - offsetToMidBaseline.x, 0); Vector3 tangent = new Vector3(x1 * (boundsMaxX - boundsMinX) + boundsMinX, y1) - new Vector3(offsetToMidBaseline.x, y0); float dot = Mathf.Acos(Vector3.Dot(horizontal, tangent.normalized)) * 57.2957795f; Vector3 cross = Vector3.Cross(horizontal, tangent); float angle = cross.z > 0 ? dot : 360 - dot; matrix = Matrix4x4.TRS(new Vector3(0, y0, 0), Quaternion.Euler(0, 0, angle), Vector3.one); vertices[vertexIndex + 0] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 0]); vertices[vertexIndex + 1] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 1]); vertices[vertexIndex + 2] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 2]); vertices[vertexIndex + 3] = matrix.MultiplyPoint3x4(vertices[vertexIndex + 3]); vertices[vertexIndex + 0] += offsetToMidBaseline; vertices[vertexIndex + 1] += offsetToMidBaseline; vertices[vertexIndex + 2] += offsetToMidBaseline; vertices[vertexIndex + 3] += offsetToMidBaseline; } // Upload the mesh with the revised information m_TextComponent.UpdateVertexData(); yield return(null); // new WaitForSeconds(0.025f); } }
//----------------------------------------------------------------- void Update() { //判断旋转 if (Input.GetMouseButtonDown(1)) //鼠标右键刚刚按下了 { { if (m_bMouseRightKeyDown == false) { m_bMouseRightKeyDown = true; Vector3 kMousePos = Input.mousePosition; m_fLastMousePosX = kMousePos.x; m_fLastMousePosY = kMousePos.y; } } } else if (Input.GetMouseButtonUp(1)) //鼠标右键刚刚抬起了 { { if (m_bMouseRightKeyDown == true) { m_bMouseRightKeyDown = false; m_fLastMousePosX = 0; m_fLastMousePosY = 0; } } } else if (Input.GetMouseButton(1)) //鼠标右键处于按下状态中 { { if (m_bMouseRightKeyDown) { Vector3 kMousePos = Input.mousePosition; float fDeltaX = kMousePos.x - m_fLastMousePosX; float fDeltaY = kMousePos.y - m_fLastMousePosY; m_fLastMousePosX = kMousePos.x; m_fLastMousePosY = kMousePos.y; Vector3 kNewEuler = transform.eulerAngles; kNewEuler.x += -(fDeltaY * rotateSpeed); kNewEuler.y += (fDeltaX * rotateSpeed); transform.eulerAngles = kNewEuler; } } } //判断位移 float fMoveDeltaX = 0.0f; float fMoveDeltaZ = 0.0f; float fMoveDeltaVertical = 0f; float fDeltaTime = Time.deltaTime; if (Input.GetKey(KeyCode.A)) { fMoveDeltaX -= moveSpeed * fDeltaTime; } if (Input.GetKey(KeyCode.D)) { fMoveDeltaX += moveSpeed * fDeltaTime; } if (Input.GetKey(KeyCode.W)) { fMoveDeltaZ += moveSpeed * fDeltaTime; } if (Input.GetKey(KeyCode.S)) { fMoveDeltaZ -= moveSpeed * fDeltaTime; } if (Input.GetKey(KeyCode.Q)) { fMoveDeltaVertical -= moveSpeed * fDeltaTime; } if (Input.GetKey(KeyCode.E)) { fMoveDeltaVertical += moveSpeed * fDeltaTime; } if (fMoveDeltaX != 0.0f || fMoveDeltaZ != 0.0f || fMoveDeltaVertical != 0.0f) { Vector3 kForward = transform.forward; Vector3 kRight = Vector3.Cross(kUpDirection, kForward); Vector3 kNewPos = transform.position; kNewPos += kRight * fMoveDeltaX; kNewPos += kForward * fMoveDeltaZ; kNewPos.y += fMoveDeltaVertical; transform.position = kNewPos; } }
private void On_MouseMove(object sender, MouseEventArgs e) { Point pos = e.Location; if (m_leftDown) { // Calculate yaw to look around with a mouse m_direction = Vector3.Transform(m_direction, Matrix3.CreateFromAxisAngle(m_up, -m_mouseSpeedX * (pos.X - m_prevMouseP.X))); // Pitch is limited to m_pitchLimit float angle = m_mouseSpeedY * (pos.Y - m_prevMouseP.Y); if ((Pitch < m_pitchLimit || angle > 0) && (Pitch > -m_pitchLimit || angle < 0)) { m_direction = Vector3.Transform(m_direction, Matrix3.CreateFromAxisAngle(Vector3.Cross(m_up, m_direction), angle)); } } m_prevMouseP = pos; }
public static float AngleSigned(Vector3 v1, Vector3 v2, Vector3 n) { return(Mathf.Atan2( Vector3.Dot(n, Vector3.Cross(v1, v2)), Vector3.Dot(v1, v2)) * Mathf.Rad2Deg); }
//static type-specific methods /// <summary> /// Determines the cross-product of two Vector3 /// </summary> /// <param name="a">the first vector to be used in the cross-product calculation</param> /// <param name="b">the second vector to be used in the cross-product calculation</param> /// <returns>the cross-product of two vector</returns> public static Vector3 Cross(Vector3 a, Vector3 b) { return a.Cross(b); }
/// <summary> /// Gets the shortest arc quaternion to rotate this vector to the destination vector. /// </summary> /// <param name="destination"></param> /// <param name="fallbackAxis"></param> /// <returns></returns> /// <remarks> /// Don't call this if you think the dest vector can be close to the inverse /// of this vector, since then ANY axis of rotation is ok. /// </remarks> public Quaternion GetRotationTo( Vector3 destination, Vector3 fallbackAxis ) { // Based on Stan Melax's article in Game Programming Gems Quaternion q; // Copy, since cannot modify local Vector3 v0 = new Vector3( this.x, this.y, this.z ); Vector3 v1 = destination; // normalize both vectors v0.Normalize(); v1.Normalize(); // get the cross product of the vectors Vector3 c = v0.Cross( v1 ); Real d = v0.Dot( v1 ); // If dot == 1, vectors are the same if( d >= 1.0f ) { return Quaternion.Identity; } if( d < ( 1e-6f - 1.0f ) ) { if( fallbackAxis != Vector3.Zero ) { // rotate 180 degrees about the fallback axis q = Quaternion.FromAngleAxis( Utility.PI, fallbackAxis ); } else { // Generate an axis Vector3 axis = Vector3.UnitX.Cross( this ); if( axis.IsZeroLength ) // pick another if colinear { axis = Vector3.UnitY.Cross( this ); } axis.Normalize(); q = Quaternion.FromAngleAxis( Utility.PI, axis ); } } else { Real s = Utility.Sqrt( ( 1 + d ) * 2 ); Real inverse = 1 / s; q.x = c.x * inverse; q.y = c.y * inverse; q.z = c.z * inverse; q.w = s * 0.5f; } return q; }
IEnumerator TransformSelected(TransformType transType) { isTransforming = true; totalScaleAmount = 0; totalRotationAmount = Quaternion.identity; Vector3 originalPivot = pivotPoint; Vector3 planeNormal = (transform.position - originalPivot).normalized; Vector3 axis = GetNearAxisDirection(); Vector3 projectedAxis = Vector3.ProjectOnPlane(axis, planeNormal).normalized; Vector3 previousMousePosition = Vector3.zero; List <ICommand> transformCommands = new List <ICommand>(); for (int i = 0; i < targetRootsOrdered.Count; i++) { transformCommands.Add(new TransformCommand(this, targetRootsOrdered[i])); } while (!Input.GetMouseButtonUp(0)) { Ray mouseRay = myCamera.ScreenPointToRay(Input.mousePosition); Vector3 mousePosition = Geometry.LinePlaneIntersect(mouseRay.origin, mouseRay.direction, originalPivot, planeNormal); if (previousMousePosition != Vector3.zero && mousePosition != Vector3.zero) { if (transType == TransformType.Move) { float moveAmount = ExtVector3.MagnitudeInDirection(mousePosition - previousMousePosition, projectedAxis) * moveSpeedMultiplier; Vector3 movement = axis * moveAmount; for (int i = 0; i < targetRootsOrdered.Count; i++) { Transform target = targetRootsOrdered[i]; target.Translate(movement, Space.World); } SetPivotPointOffset(movement); } else if (transType == TransformType.Scale) { Vector3 projected = (nearAxis == Axis.Any) ? transform.right : projectedAxis; float scaleAmount = ExtVector3.MagnitudeInDirection(mousePosition - previousMousePosition, projected) * scaleSpeedMultiplier; //WARNING - There is a bug in unity 5.4 and 5.5 that causes InverseTransformDirection to be affected by scale which will break negative scaling. Not tested, but updating to 5.4.2 should fix it - https://issuetracker.unity3d.com/issues/transformdirection-and-inversetransformdirection-operations-are-affected-by-scale Vector3 localAxis = (space == TransformSpace.Local && nearAxis != Axis.Any) ? mainTargetRoot.InverseTransformDirection(axis) : axis; Vector3 targetScaleAmount = Vector3.one; if (nearAxis == Axis.Any) { targetScaleAmount = (ExtVector3.Abs(mainTargetRoot.localScale.normalized) * scaleAmount); } else { targetScaleAmount = localAxis * scaleAmount; } for (int i = 0; i < targetRootsOrdered.Count; i++) { Transform target = targetRootsOrdered[i]; Vector3 targetScale = target.localScale + targetScaleAmount; if (pivot == TransformPivot.Pivot) { target.localScale = targetScale; } else if (pivot == TransformPivot.Center) { if (scaleType == ScaleType.FromPoint) { target.SetScaleFrom(originalPivot, targetScale); } else if (scaleType == ScaleType.FromPointOffset) { target.SetScaleFromOffset(originalPivot, targetScale); } } } totalScaleAmount += scaleAmount; } else if (transType == TransformType.Rotate) { float rotateAmount = 0; Vector3 rotationAxis = axis; if (nearAxis == Axis.Any) { Vector3 rotation = transform.TransformDirection(new Vector3(Input.GetAxis("Mouse Y"), -Input.GetAxis("Mouse X"), 0)); Quaternion.Euler(rotation).ToAngleAxis(out rotateAmount, out rotationAxis); rotateAmount *= allRotateSpeedMultiplier; } else { if (circularRotationMethod) { float angle = Vector3.SignedAngle(previousMousePosition - originalPivot, mousePosition - originalPivot, axis); rotateAmount = angle * rotateSpeedMultiplier; } else { Vector3 projected = (nearAxis == Axis.Any || ExtVector3.IsParallel(axis, planeNormal)) ? planeNormal : Vector3.Cross(axis, planeNormal); rotateAmount = (ExtVector3.MagnitudeInDirection(mousePosition - previousMousePosition, projected) * (rotateSpeedMultiplier * 100f)) / GetDistanceMultiplier(); } } for (int i = 0; i < targetRootsOrdered.Count; i++) { Transform target = targetRootsOrdered[i]; if (pivot == TransformPivot.Pivot) { target.Rotate(rotationAxis, rotateAmount, Space.World); } else if (pivot == TransformPivot.Center) { target.RotateAround(originalPivot, rotationAxis, rotateAmount); } } totalRotationAmount *= Quaternion.Euler(rotationAxis * rotateAmount); } } previousMousePosition = mousePosition; yield return(null); } for (int i = 0; i < transformCommands.Count; i++) { ((TransformCommand)transformCommands[i]).StoreNewTransformValues(); } CommandGroup commandGroup = new CommandGroup(); commandGroup.Set(transformCommands); UndoRedoManager.Insert(commandGroup); totalRotationAmount = Quaternion.identity; totalScaleAmount = 0; isTransforming = false; SetTranslatingAxis(transformType, Axis.None); SetPivotPoint(); }
/// <summary> /// Gets the shortest arc quaternion to rotate this vector /// to the destination vector. /// </summary> /// <remarks> /// If you call this with a dest vector that is close to the inverse /// of this vector, we will rotate 180 degrees around the 'fallbackAxis' /// (if specified, or a generated axis if not) since in this case /// ANY axis of rotation is valid. /// </remarks> public Quaternion GetRotationTo(Vector3 destination, Vector3 fallbackAxis) { // Based on Stan Melax's article in Game Programming Gems Quaternion q = new Quaternion(); Vector3 v0 = new Vector3(this.x, this.y, this.z); Vector3 v1 = destination; // normalize both vectors v0.Normalize(); v1.Normalize(); // get the cross product of the vectors Vector3 c = v0.Cross(v1); // If the cross product approaches zero, we get unstable because ANY axis will do // when v0 == -v1 float d = v0.Dot(v1); // If dot == 1, vectors are the same if (d >= 1.0f) { return Quaternion.Identity; } if (d < (1e-6f - 1.0f)) { if (fallbackAxis != Vector3.Zero) // rotate 180 degrees about the fallback axis q = Quaternion.FromAngleAxis((float)Math.PI, fallbackAxis); else { // Generate an axis Vector3 axis = Vector3.UnitX.Cross(this); if (axis.IsZero) // pick another if colinear axis = Vector3.UnitY.Cross(this); axis.Normalize(); q = Quaternion.FromAngleAxis((float)Math.PI, axis); } } else { float s = MathUtil.Sqrt( (1+d) * 2 ); float inverse = 1 / s; q.x = c.x * inverse; q.y = c.y * inverse; q.z = c.z * inverse; q.w = s * 0.5f; q.Normalize(); } return q; }
public Path processPoints() { if (nature == Nature.Normal) { path = new Path(Vector3.zero); //Create new path to exploit if (points.Count > 1) { Vector3 direction = points[1] - points[0]; // Get first direction from start to second point bool changeDirection = false; List <Vector3> pathPoints = new List <Vector3>(); pathPoints.Add(points[0]); // Add first ANCHOR pathPoints.Add(new Vector3(points[0].x + (points[1].x - points[0].x) / 2f, points[0].y + (points[1].y - points[0].y) / 2f, points[0].z + (points[1].z - points[0].z) / 2f)); // Add first PIVOT if (points.Count > 2) { if (Vector3.Cross(direction.normalized, (points[2] - points[1]).normalized) != Vector3.zero) // first is short { direction = points[2] - points[1]; //New direction pathPoints.Add(points[1]); //PIVOT pathPoints.Add(new Vector3(points[1].x + (points[2].x - points[1].x) / 2f, points[1].y + (points[2].y - points[1].y) / 2f, points[1].z + (points[2].z - points[1].z) / 2f)); //ANCHOR pathPoints.Add(points[2]); //PIVOT } for (int i = 2; i < points.Count - 2;) { if (Vector3.Cross(direction.normalized, (points[i + 1] - points[i]).normalized) == Vector3.zero) // if on same line so go to next point { changeDirection = false; i++; } else if (Vector3.Cross(direction.normalized, (points[i + 1] - points[i]).normalized) != Vector3.zero) { if (changeDirection) { pathPoints.Add(points[i]);//PIVOT pathPoints.Add(new Vector3(points[i].x + (points[i + 1].x - points[i].x) / 2f, points[i].y + (points[i + 1].y - points[i].y) / 2f, points[i].z + (points[i + 1].z - points[i].z) / 2f)); //ANCHOR pathPoints.Add(points[i + 1]); //PIVOT direction = points[i + 1] - points[i]; i++; } else { i--; pathPoints.Add(new Vector3(points[i - 1].x + (points[i].x - points[i - 1].x) / 4f, points[i - 1].y + (points[i].y - points[i - 1].y) / 4f, points[i - 1].z + (points[i].z - points[i - 1].z) / 4f)); //PIVOT pathPoints.Add(points[i]); //ANCHOR pathPoints.Add(new Vector3(points[i].x + (points[i + 1].x - points[i].x) / (4f / 3f), points[i].y + (points[i + 1].y - points[i].y) / (4f / 3f), points[i].z + (points[i + 1].z - points[i].z) / (4f / 3f))); //PIVOT i++; i++; pathPoints.Add(new Vector3(points[i - 1].x + (points[i].x - points[i - 1].x) / 4f, points[i - 1].y + (points[i].y - points[i - 1].y) / 4f, points[i - 1].z + (points[i].z - points[i - 1].z) / 4f)); //PIVOT pathPoints.Add(points[i]); //ANCHOR pathPoints.Add(new Vector3(points[i].x + (points[i + 1].x - points[i].x) / (4f / 3f), points[i].y + (points[i + 1].y - points[i].y) / (4f / 3f), points[i].z + (points[i + 1].z - points[i].z) / (4f / 3f))); //PIVOT direction = points[i + 1] - points[i]; i++; changeDirection = true; } } } if (Vector3.Cross((points[points.Count - 2] - points[points.Count - 3]).normalized, (points[points.Count - 1] - points[points.Count - 2]).normalized) != Vector3.zero) // last is short { pathPoints.Add(points[points.Count - 3]); //PIVOT pathPoints.Add(new Vector3(points[points.Count - 3].x + (points[points.Count - 2].x - points[points.Count - 3].x) / 2f, points[points.Count - 3].y + (points[points.Count - 2].y - points[points.Count - 3].y) / 2f, points[points.Count - 3].z + (points[points.Count - 2].z - points[points.Count - 3].z) / 2f)); //ANCHOR pathPoints.Add(points[points.Count - 2]); //PIVOT } } pathPoints.Add(new Vector3(points[points.Count - 2].x + (points[points.Count - 1].x - points[points.Count - 2].x) / 2f, points[points.Count - 2].y + (points[points.Count - 1].y - points[points.Count - 2].y) / 2f, points[points.Count - 2].z + (points[points.Count - 1].z - points[points.Count - 2].z) / 2f)); // Add last PIVOT pathPoints.Add(points[points.Count - 1]); //add last ANCHOR if (debug) ////////DEBUG/////// { for (int i = 0; i < pathPoints.Count; i++) { GameObject g; g = GameObject.CreatePrimitive(PrimitiveType.Cube); g.transform.position = pathPoints[i]; g.name = i.ToString(); } for (int i = 0; i < pathPoints.Count; i++) { GameObject g; if (i % 3 == 0) { g = GameObject.CreatePrimitive(PrimitiveType.Cube); } else { g = GameObject.CreatePrimitive(PrimitiveType.Sphere); } g.transform.position = pathPoints[i]; } } if (points.Count > 2) { for (int i = 1; i < pathPoints.Count / 3; i++) { path.AddSegment(Vector3.zero); } } for (int i = 0; i < path.NumPoints; i++) { path[i] = pathPoints[i]; } } } if (nature == Nature.Anchor) { path = new Path(Vector3.zero); if (debug) ////////DEBUG/////// { for (int i = 0; i < points.Count; i++) { GameObject g; if (i % 3 == 0) { g = GameObject.CreatePrimitive(PrimitiveType.Cube); } else { g = GameObject.CreatePrimitive(PrimitiveType.Sphere); } g.transform.position = points[i]; } } if (points.Count > 4) { for (int i = 1; i < points.Count / 3; i++) { path.AddSegment(Vector3.zero); } } for (int i = 0; i < path.NumPoints; i++) { path[i] = points[i]; } } return(path); }
public static Quaternion Align(this Transform transform, Vector3 normAlignVector, TransformAxis alignmentAxis) { Vector3 axis = transform.up; if (alignmentAxis != TransformAxis.PositiveY) { if (alignmentAxis == TransformAxis.PositiveX) { axis = transform.right; } else if (alignmentAxis == TransformAxis.NegativeX) { axis = -transform.right; } else if (alignmentAxis == TransformAxis.NegativeY) { axis = -transform.up; } else if (alignmentAxis == TransformAxis.PositiveZ) { axis = transform.forward; } else if (alignmentAxis == TransformAxis.NegativeZ) { axis = -transform.forward; } } float alignment = Vector3.Dot(axis, normAlignVector); if (1.0f - alignment < 1e-5f) { return(Quaternion.identity); } Vector3 rotAxis = Vector3.zero; // Check if the alignment axis is aligned with the alignment vector in the opposite direction if (alignment + 1.0f < 1e-5f) { if (alignmentAxis == TransformAxis.PositiveX) { rotAxis = transform.up; } else if (alignmentAxis == TransformAxis.NegativeX) { rotAxis = -transform.up; } else if (alignmentAxis == TransformAxis.PositiveY) { rotAxis = transform.right; } else if (alignmentAxis == TransformAxis.NegativeY) { rotAxis = -transform.right; } else if (alignmentAxis == TransformAxis.PositiveZ) { rotAxis = transform.up; } else if (alignmentAxis == TransformAxis.NegativeZ) { rotAxis = -transform.up; } } else { rotAxis = Vector3.Normalize(Vector3.Cross(axis, normAlignVector)); } float rotAngle = Vector3Ex.SignedAngle(axis, normAlignVector, rotAxis); transform.Rotate(rotAxis, rotAngle, Space.World); return(Quaternion.AngleAxis(rotAngle, rotAxis)); }
void CalculateCurveFit(Common.Vbo handle) { int num = handle.selectedVertices.Count; var pointsMat = new MathNet.Numerics.LinearAlgebra.Double.DenseMatrix(num, 3); var points = new Vector3[num]; //get selected points for (int i = 0; i < num; i++) { pointsMat[i, 0] = handle.verticesData.vertices[handle.selectedVertices[i]].X; pointsMat[i, 1] = handle.verticesData.vertices[handle.selectedVertices[i]].Y; pointsMat[i, 2] = handle.verticesData.vertices[handle.selectedVertices[i]].Z; points[i] = handle.verticesData.vertices[handle.selectedVertices[i]]; } //find the plane which holds the least distance to all ponits using SVD Common.Plane curve_plane = NormalPlane(pointsMat); curve_plane.valid = true; Planes[GetSelectedVbOIndex() - 1][CURVEPLANE_INDEX] = curve_plane; if (Planes[GetSelectedVbOIndex() - 1][OCCLUSALPLANE_INDEX] != null && Planes[GetSelectedVbOIndex() - 1][OCCLUSALPLANE_INDEX].valid) { double angle = Planes[GetSelectedVbOIndex() - 1][CURVEPLANE_INDEX].Angle2Plane(Planes[0][OCCLUSALPLANE_INDEX]); lb_curve2occlusalPlane.Text = "Angle to Occlusal Plane: " + angle.ToString("F2"); } //calculate sum of distances to this plane double sumOfSquaredDistances = 0; double[] z_distances = new double[num]; for (int i = 0; i < num; ++i) { double d = curve_plane.Distance2Point(points[i]); z_distances[i] = d; sumOfSquaredDistances += Math.Pow(d, 2); } double rmse_z = Math.Sqrt(sumOfSquaredDistances / num); // find the x and y direction on the plane var p0 = new Vector3(curve_plane.ProjectPointOnPlane(new Vector3(0, 0, 0))); var px = new Vector3(curve_plane.ProjectPointOnPlane(points[num - 1] - points[0])); //new Vector3(1, 0, 0))); var py = new Vector3(curve_plane.ProjectPointOnPlane(Vector3.Cross(curve_plane.GetNormal(), px))); //new Vector3(0, 1, 0))); var pvx = (px - p0); var pvy = (py - p0); pvx.Normalize(); pvy.Normalize(); //project 3D points on the plane and create a 2D point set var points2DX = new double[num]; var points2DY = new double[num]; for (int i = 0; i < num; ++i) { points2DX[i] = Vector3.Dot(pvx, points[i] - p0); points2DY[i] = Vector3.Dot(pvy, points[i] - p0); } //check and fix inverse y mode if (points2DY[0] < points2DY[points2DY.Length / 2]) { points2DY = points2DY.Select(el => - el).ToArray(); } //move points to fit on the screen var xMin = points2DX.Min(); var yMin = points2DY.Min(); for (int i = 0; i < num; ++i) { points2DX[i] -= xMin; points2DY[i] -= yMin; points2DX[i] += 10; points2DY[i] += 10; } //drawing projected points var graphics = pl_curveFit.CreateGraphics(); graphics.Clear(Color.White); for (int i = 0; i < num; ++i) { DrawPoint2DOnControl(graphics, new PointF((float)points2DX[i], (float)points2DY[i]), Color.Black, 4); } //DrawPoint2DOnControl(graphics, new PointF((float)10, (float)20), Color.Red, 10); //change of parameter var diffx = Diff(points2DX); var diffy = Diff(points2DY); diffx = diffx.Select(el => el * el).ToArray(); diffy = diffy.Select(el => el * el).ToArray(); double[] t = new double[num]; for (int i = 0; i < num; ++i) { if (i > 0) { t[i] = Math.Sqrt(diffx[i] + diffy[i]) + t[i - 1]; } else { t[i] = Math.Sqrt(diffx[i] + diffy[i]); } } //fit curve params int deg = (int)nUpDown_order.Value; FitFunction fitFunction = config.fitFunction; //fit x and y to t DenseVector Wx; DenseVector Wy; try { //f = Fit.Polynomial(xdata, ydata, order); Wx = FitLeastSquaresBasis(t, points2DX, fitFunction, deg); Wy = FitLeastSquaresBasis(t, points2DY, fitFunction, deg); } catch (Exception e) { Common.Logger.Log("MainForm", "curveFit.cs", "CalculateCurveFit", e.Message); MessageBox.Show("The order of polynomial is too high and " + "results are unstable. Please use a lower " + "degree polynomial.", "Error in Curve Fitting"); return; } // create polynomial curve struct (for later to match to the wire brackets) CurveFit[GetSelectedVbOIndex() - 1].CoeffsX = Wx; CurveFit[GetSelectedVbOIndex() - 1].CoeffsY = Wy; CurveFit[GetSelectedVbOIndex() - 1].degree = deg; CurveFit[GetSelectedVbOIndex() - 1].minT = t.Min() - 5; CurveFit[GetSelectedVbOIndex() - 1].maxT = t.Max() + 5; CurveFit[GetSelectedVbOIndex() - 1].fitFunction = fitFunction; //calculate xx and yy //const double stepSize = 0.01; //double mint = t.Min(); //double maxt = t.Max(); //int numCurve = (int)((maxt - mint) / stepSize); //double[] tt = new double[numCurve]; //for (int i = 0; i < numCurve; i++) //{ // tt[i] = mint + stepSize * i; //} //var TT = MakeBasis(tt, fitFunction, deg); //var XX = TT * Wx; //var YY = TT * Wy; Tuple <DenseVector, DenseVector> tempTuple = ParametricPolynomial_to_2DPoints(CurveFit[GetSelectedVbOIndex() - 1]); DenseVector XX = tempTuple.Item1; DenseVector YY = tempTuple.Item2; DrawCurve(graphics, XX, YY, Color.Blue); //least squares //DenseVector W; //try //{ // //f = Fit.Polynomial(xdata, ydata, order); // W = FitLeastSquaresBasis(xdata, ydata, fitFunction, deg); //} //catch (Exception e) //{ // MessageBox.Show("The order of polynomial is too high and results are unstable. Please use a lower degree polynomial.", "Error in Curve Fitting"); // return; //} //draw the blue curve //DrawCurve(graphics, W, xdata.Min()-4, xdata.Max()+4, fitFunction, deg); //calculate Error //var rmse_xy = CalculatePerpendicularDistancePointToCurve(xdata, ydata, W, fitFunction, deg, graphics); double[] xy_distances; int[] closestPointsIndexOnCurve; var rmse_xy = CalculatePerpendicularDistancePointToCurve(points2DX, points2DY, XX, YY, graphics, out xy_distances, out closestPointsIndexOnCurve); //fill the list view with point distances lv_pointDistance.Clear(); lv_pointDistance.Columns.Add("Pt", 20, HorizontalAlignment.Center); lv_pointDistance.Columns.Add("off", 40, HorizontalAlignment.Center); lv_pointDistance.Columns.Add("intra", 40, HorizontalAlignment.Center); for (int i = 0; i < num; ++i) { lv_pointDistance.Items.Add(new ListViewItem(new string[] { i.ToString(), z_distances[i].ToString("F2"), xy_distances[i].ToString("F2") })); } if (lv_pointDistance.Items.Count > 0) { lv_pointDistance.Items[0].Selected = true; } lb_curvefit_rmse_xy.Text = "in-plane RMS Error: " + rmse_xy.ToString("F2"); lb_curvefit_rmse_z.Text = "off-plane RMS Error: " + rmse_z.ToString("F2"); // write results to disk string resultsDir = "Results"; if (!System.IO.Directory.Exists(resultsDir)) { System.IO.Directory.CreateDirectory(resultsDir); } string save_path = System.IO.Path.Combine( resultsDir, "CurveFitResults_" + GetSelectedVbOIndex().ToString() + ".csv"); var writer = new StreamWriter(save_path); writer.WriteLine("Point Number,X,Y,Z,Projected on WirePlane (X),Projected on WirePlane (Y)," + "Nearest Point on 2D Wire (projected wire) (X),Nearest Point on 2D Wire(projected wire)(Y)," + "InPlane Distance,OffPlane Distance"); for (int i = 0; i < num; ++i) { writer.Write(i.ToString() + ","); writer.Write(points[i].X.ToString() + ","); writer.Write(points[i].Y.ToString() + ","); writer.Write(points[i].Z.ToString() + ","); writer.Write(points2DX[i].ToString() + ","); writer.Write(points2DY[i].ToString() + ","); writer.Write(XX[closestPointsIndexOnCurve[i]].ToString() + ","); writer.Write(YY[closestPointsIndexOnCurve[i]].ToString() + ","); writer.Write(xy_distances[i].ToString() + ","); writer.Write(z_distances[i].ToString()); writer.WriteLine(""); } writer.Close(); status.Text = "Results of curve fitting are saved in: " + save_path; }
public Vector3 CalculateNormal(Vector3 a, Vector3 b, Vector3 c) { Vector3 planeNormal = Vector3.Cross(c - a, b - a).normalized * 0.025f; return(planeNormal); }
public static void RecalculateTangents(this Mesh mesh) { //speed up math by copying the mesh arrays int[] triangles = mesh.triangles; Vector3[] vertices = mesh.vertices; Vector2[] uv = mesh.uv; Vector3[] normals = mesh.normals; //variable definitions int triangleCount = triangles.Length; int vertexCount = vertices.Length; Vector3[] tan1 = new Vector3[vertexCount]; Vector3[] tan2 = new Vector3[vertexCount]; Vector4[] tangents = new Vector4[vertexCount]; for (long a = 0; a < triangleCount; a += 3) { long i1 = triangles[a + 0]; long i2 = triangles[a + 1]; long i3 = triangles[a + 2]; Vector3 v1 = vertices[i1]; Vector3 v2 = vertices[i2]; Vector3 v3 = vertices[i3]; Vector2 w1 = uv[i1]; Vector2 w2 = uv[i2]; Vector2 w3 = uv[i3]; float x1 = v2.x - v1.x; float x2 = v3.x - v1.x; float y1 = v2.y - v1.y; float y2 = v3.y - v1.y; float z1 = v2.z - v1.z; float z2 = v3.z - v1.z; float s1 = w2.x - w1.x; float s2 = w3.x - w1.x; float t1 = w2.y - w1.y; float t2 = w3.y - w1.y; float r = 1.0f / (s1 * t2 - s2 * t1); Vector3 sdir = new Vector3((t2 * x1 - t1 * x2) * r, (t2 * y1 - t1 * y2) * r, (t2 * z1 - t1 * z2) * r); Vector3 tdir = new Vector3((s1 * x2 - s2 * x1) * r, (s1 * y2 - s2 * y1) * r, (s1 * z2 - s2 * z1) * r); tan1[i1] += sdir; tan1[i2] += sdir; tan1[i3] += sdir; tan2[i1] += tdir; tan2[i2] += tdir; tan2[i3] += tdir; } for (long a = 0; a < vertexCount; ++a) { Vector3 n = normals[a]; Vector3 t = tan1[a]; //Vector3 tmp = (t - n * Vector3.Dot(n, t)).normalized; //tangents[a] = new Vector4(tmp.x, tmp.y, tmp.z); Vector3.OrthoNormalize(ref n, ref t); tangents[a].x = t.x; tangents[a].y = t.y; tangents[a].z = t.z; tangents[a].w = (Vector3.Dot(Vector3.Cross(n, t), tan2[a]) < 0.0f) ? -1.0f : 1.0f; } mesh.tangents = tangents; }
/// <summary> /// Update the rotation forces. /// </summary> public override void UpdateRotation() { var updateNormalRotation = m_Stopping; var targetNormal = m_Stopping ? (m_StopGravityDirection.sqrMagnitude > 0 ? -m_StopGravityDirection : -m_CharacterLocomotion.GravityDirection) : m_CharacterLocomotion.Up; if (!m_Stopping) { // If the depth offset isn't zero then use two raycasts to determine the ground normal. This will allow a long character (such as a horse) to correctly // adjust to a slope. if (m_DepthOffset != 0) { var frontPoint = m_Transform.position; bool frontHit; RaycastHit raycastHit; if ((frontHit = Physics.Raycast(m_Transform.TransformPoint(0, 0.1f, m_DepthOffset * Mathf.Sign(m_CharacterLocomotion.InputVector.y)), -m_CharacterLocomotion.Up, out raycastHit, m_Distance, m_CharacterLayerManager.SolidObjectLayers, QueryTriggerInteraction.Ignore))) { frontPoint = raycastHit.point; targetNormal = raycastHit.normal; } var backPoint = frontPoint; if (Physics.Raycast(m_Transform.TransformPoint(0, 0.1f, m_DepthOffset * -Mathf.Sign(m_CharacterLocomotion.InputVector.y)), -m_CharacterLocomotion.Up, out raycastHit, m_Distance, m_CharacterLayerManager.SolidObjectLayers, QueryTriggerInteraction.Ignore)) { if (frontHit) { if (m_NormalizeDirection) { backPoint = raycastHit.point; var direction = (frontPoint - backPoint).normalized; targetNormal = Vector3.Cross(direction, Vector3.Cross(m_CharacterLocomotion.Up, direction)).normalized; } else { targetNormal = (targetNormal + raycastHit.normal).normalized; } } else { targetNormal = raycastHit.normal; } } m_CharacterLocomotion.GravityDirection = -targetNormal; updateNormalRotation = true; } else { var hitCount = m_CharacterLocomotion.Cast(-m_CharacterLocomotion.Up * m_Distance, m_CharacterLocomotion.PlatformMovement + m_CharacterLocomotion.Up * m_CharacterLocomotion.ColliderSpacing, ref m_CombinedRaycastHits, ref m_ColliderIndexMap); // The character hit the ground if any hit points are below the collider. for (int i = 0; i < hitCount; ++i) { var closestRaycastHit = QuickSelect.SmallestK(m_CombinedRaycastHits, hitCount, i, m_RaycastHitComparer); // The hit point has to be under the collider for the character to align to it. var activeCollider = m_CharacterLocomotion.ColliderCount > 1 ? m_CharacterLocomotion.Colliders[m_ColliderIndexMap[closestRaycastHit]] : m_CharacterLocomotion.Colliders[0]; if (!MathUtility.IsUnderCollider(m_Transform, activeCollider, closestRaycastHit.point)) { continue; } m_CharacterLocomotion.GravityDirection = -closestRaycastHit.normal; updateNormalRotation = true; break; } } } // The rotation is affected by aligning to the ground or having a different up rotation from gravity. if (updateNormalRotation) { Rotate(targetNormal); } }
public static Vector2 GetNormal(this Vector2 v) { var normal = Vector3.Cross(new Vector3(v.x, v.y, 0), new Vector3(0, 0, 1)).normalized; return(new Vector2(normal.x, normal.y)); }
public static void LookAt(ref Vector3 forward, ref Vector3 up, out Matrix3 result) { var Z = forward.Normalize(); var X = up.Cross(Z).Normalize(); var Y = Z.Cross(X); result.X = X; result.Y = Y; result.Z = Z; }
// based on noontz's code here: http://forum.unity3d.com/threads/38984-How-to-Calculate-Mesh-Tangents public static void UpdateTangents(Mesh mesh) { ProfileTimer.Push("UpdateTangents"); Vector4[] tangents = new Vector4[mesh.vertexCount]; int triangleCount = mesh.triangles.Length / 3; Vector3[] tan1 = new Vector3[mesh.vertexCount]; Vector3[] tan2 = new Vector3[mesh.vertexCount]; int tri = 0; Vector3 sdir = new Vector3(); Vector3 tdir = new Vector3(); for (int i = 0; i < triangleCount; i++) { int i1 = mesh.triangles[tri]; int i2 = mesh.triangles[tri + 1]; int i3 = mesh.triangles[tri + 2]; Vector3 v1 = mesh.vertices[i1]; Vector3 v2 = mesh.vertices[i2]; Vector3 v3 = mesh.vertices[i3]; Vector2 w1 = mesh.uv[i1]; Vector2 w2 = mesh.uv[i2]; Vector2 w3 = mesh.uv[i3]; float x1 = v2.x - v1.x; float x2 = v3.x - v1.x; float y1 = v2.y - v1.y; float y2 = v3.y - v1.y; float z1 = v2.z - v1.z; float z2 = v3.z - v1.z; float s1 = w2.x - w1.x; float s2 = w3.x - w1.x; float t1 = w2.y - w1.y; float t2 = w3.y - w1.y; float r = 1.0f / (s1 * t2 - s2 * t1); sdir.x = (t2 * x1 - t1 * x2); sdir.y = (t2 * y1 - t1 * y2); sdir.z = (t2 * z1 - t1 * z2); sdir *= r; tdir.x = (s1 * x2 - s2 * x1); tdir.y = (s1 * y2 - s2 * y1); tdir.z = (s1 * z2 - s2 * z1); tdir *= r; tan1[i1] += sdir; tan1[i2] += sdir; tan1[i3] += sdir; tan2[i1] += tdir; tan2[i2] += tdir; tan2[i3] += tdir; tri += 3; } for (int i = 0; i < mesh.vertexCount; i++) { Vector3 n = mesh.normals[i]; Vector3 t = tan1[i]; // Gram-Schmidt orthogonalize Vector3.OrthoNormalize(ref n, ref t); tangents[i].x = t.x; tangents[i].y = t.y; tangents[i].z = t.z; // Calculate handedness tangents[i].w = (Vector3.Dot(Vector3.Cross(n, t), tan2[i]) < 0.0f) ? -1.0f : 1.0f; } mesh.tangents = tangents; ProfileTimer.Pop("UpdateTangents"); }
public void SplitMesh(Transform meshTransform, Mesh mesh, Plane plane, bool cap) { //Debug Code Start float startTime = Time.realtimeSinceStartup; //Debug Code Stop Vector3[] meshVertices = mesh.vertices; Vector2[] meshUV = mesh.uv; int newTriangles = 0; int newEdges = 0; for (int i = 0; i < meshVertices.Length; i += 3) { float v0 = plane.GetDistanceToPoint(meshTransform.TransformPoint(meshVertices[i])); float v1 = plane.GetDistanceToPoint(meshTransform.TransformPoint(meshVertices[i + 1])); float v2 = plane.GetDistanceToPoint(meshTransform.TransformPoint(meshVertices[i + 2])); v0 = Mathf.Abs(v0) > 0.001?v0:0; v1 = Mathf.Abs(v1) > 0.001?v1:0; v2 = Mathf.Abs(v2) > 0.001?v2:0; if (!(v0 <= 0 && v1 <= 0 && v2 <= 0)) { newTriangles += 3; if (v0 < 0 && v1 > 0 && v2 > 0) { newTriangles += 3; } else if (v0 > 0 && v1 < 0 && v2 > 0) { newTriangles += 3; } else if (v0 > 0 && v1 > 0 && v2 < 0) { newTriangles += 3; } if (!(v0 >= 0 && v1 >= 0 && v2 >= 0)) { newEdges += 2; } else if (v0 > 0 && v1 == 0 && v2 == 0) { newEdges += 2; } else if (v0 == 0 && v1 > 0 && v2 == 0) { newEdges += 2; } else if (v0 == 0 && v1 == 0 && v2 > 0) { newEdges += 2; } } } Vector3[] vertices = new Vector3[newTriangles + newEdges * 3 / 2]; Vector2[] uv = new Vector2[newTriangles + newEdges * 3 / 2]; int[] triangles = new int[newTriangles + newEdges * 3 / 2]; int[] edges = new int[newEdges]; for (int i = 0, j = 0, k = 0; i < meshVertices.Length; i += 3) { float v0 = plane.GetDistanceToPoint(meshTransform.TransformPoint(meshVertices[i])); float v1 = plane.GetDistanceToPoint(meshTransform.TransformPoint(meshVertices[i + 1])); float v2 = plane.GetDistanceToPoint(meshTransform.TransformPoint(meshVertices[i + 2])); v0 = Mathf.Abs(v0) > 0.001?v0:0; v1 = Mathf.Abs(v1) > 0.001?v1:0; v2 = Mathf.Abs(v2) > 0.001?v2:0; if (!(v0 <= 0 && v1 <= 0 && v2 <= 0)) { if (v0 >= 0 && v1 >= 0 && v2 >= 0) { vertices[j] = meshVertices[i]; vertices[j + 1] = meshVertices[i + 1]; vertices[j + 2] = meshVertices[i + 2]; uv[j] = meshUV[i]; uv[j + 1] = meshUV[i + 1]; uv[j + 2] = meshUV[i + 2]; triangles[j] = j; triangles[j + 1] = j + 1; triangles[j + 2] = j + 2; if (v0 > 0 && v1 == 0 && v2 == 0) { edges[k] = j + 1; edges[k + 1] = j + 2; k += 2; } else if (v0 == 0 && v1 > 0 && v2 == 0) { edges[k] = j; edges[k + 1] = j + 2; k += 2; } else if (v0 == 0 && v1 == 0 && v2 > 0) { edges[k] = j; edges[k + 1] = j + 1; k += 2; } j += 3; } else if (v0 > 0 && v1 < 0 && v2 < 0) { vertices[j] = meshVertices[i]; vertices[j + 1] = meshVertices[i + 1] + (meshVertices[i] - meshVertices[i + 1]) * (1 - v0 / (v0 - v1)); vertices[j + 2] = meshVertices[i + 2] + (meshVertices[i] - meshVertices[i + 2]) * (1 - v0 / (v0 - v2)); uv[j] = meshUV[i]; uv[j + 1] = meshUV[i + 1] + (meshUV[i] - meshUV[i + 1]) * (1 - v0 / (v0 - v1)); uv[j + 2] = meshUV[i + 2] + (meshUV[i] - meshUV[i + 2]) * (1 - v0 / (v0 - v2)); triangles[j] = j; triangles[j + 1] = j + 1; triangles[j + 2] = j + 2; edges[k] = j + 1; edges[k + 1] = j + 2; k += 2; j += 3; } else if (v0 < 0 && v1 > 0 && v2 < 0) { vertices[j] = meshVertices[i] + (meshVertices[i + 1] - meshVertices[i]) * (1 - v1 / (v1 - v0)); vertices[j + 1] = meshVertices[i + 1]; vertices[j + 2] = meshVertices[i + 2] + (meshVertices[i + 1] - meshVertices[i + 2]) * (1 - v1 / (v1 - v2)); uv[j] = meshUV[i] + (meshUV[i + 1] - meshUV[i]) * (1 - v1 / (v1 - v0)); uv[j + 1] = meshUV[i + 1]; uv[j + 2] = meshUV[i + 2] + (meshUV[i + 1] - meshUV[i + 2]) * (1 - v1 / (v1 - v2)); triangles[j] = j; triangles[j + 1] = j + 1; triangles[j + 2] = j + 2; edges[k] = j; edges[k + 1] = j + 2; k += 2; j += 3; } else if (v0 < 0 && v1 < 0 && v2 > 0) { vertices[j] = meshVertices[i] + (meshVertices[i + 2] - meshVertices[i]) * (1 - v2 / (v2 - v0)); vertices[j + 1] = meshVertices[i + 1] + (meshVertices[i + 2] - meshVertices[i + 1]) * (1 - v2 / (v2 - v1)); vertices[j + 2] = meshVertices[i + 2]; uv[j] = meshUV[i] + (meshUV[i + 2] - meshUV[i]) * (1 - v2 / (v2 - v0)); uv[j + 1] = meshUV[i + 1] + (meshUV[i + 2] - meshUV[i + 1]) * (1 - v2 / (v2 - v1)); uv[j + 2] = meshUV[i + 2]; triangles[j] = j; triangles[j + 1] = j + 1; triangles[j + 2] = j + 2; edges[k] = j; edges[k + 1] = j + 1; k += 2; j += 3; } else if (v0 > 0 && v1 <= 0 && v2 < 0) { vertices[j] = meshVertices[i]; vertices[j + 1] = meshVertices[i + 1] + (meshVertices[i] - meshVertices[i + 1]) * (1 - v0 / (v0 - v1)); vertices[j + 2] = meshVertices[i + 2] + (meshVertices[i] - meshVertices[i + 2]) * (1 - v0 / (v0 - v2)); uv[j] = meshUV[i]; uv[j + 1] = meshUV[i + 1] + (meshUV[i] - meshUV[i + 1]) * (1 - v0 / (v0 - v1)); uv[j + 2] = meshUV[i + 2] + (meshUV[i] - meshUV[i + 2]) * (1 - v0 / (v0 - v2)); triangles[j] = j; triangles[j + 1] = j + 1; triangles[j + 2] = j + 2; edges[k] = j + 1; edges[k + 1] = j + 2; k += 2; j += 3; } else if (v0 <= 0 && v1 > 0 && v2 < 0) { vertices[j] = meshVertices[i] + (meshVertices[i + 1] - meshVertices[i]) * (1 - v1 / (v1 - v0)); vertices[j + 1] = meshVertices[i + 1]; vertices[j + 2] = meshVertices[i + 2] + (meshVertices[i + 1] - meshVertices[i + 2]) * (1 - v1 / (v1 - v2)); uv[j] = meshUV[i] + (meshUV[i + 1] - meshUV[i]) * (1 - v1 / (v1 - v0)); uv[j + 1] = meshUV[i + 1]; uv[j + 2] = meshUV[i + 2] + (meshUV[i + 1] - meshUV[i + 2]) * (1 - v1 / (v1 - v2)); triangles[j] = j; triangles[j + 1] = j + 1; triangles[j + 2] = j + 2; edges[k] = j; edges[k + 1] = j + 2; k += 2; j += 3; } else if (v0 <= 0 && v1 < 0 && v2 > 0) { vertices[j] = meshVertices[i] + (meshVertices[i + 2] - meshVertices[i]) * (1 - v2 / (v2 - v0)); vertices[j + 1] = meshVertices[i + 1] + (meshVertices[i + 2] - meshVertices[i + 1]) * (1 - v2 / (v2 - v1)); vertices[j + 2] = meshVertices[i + 2]; uv[j] = meshUV[i] + (meshUV[i + 2] - meshUV[i]) * (1 - v2 / (v2 - v0)); uv[j + 1] = meshUV[i + 1] + (meshUV[i + 2] - meshUV[i + 1]) * (1 - v2 / (v2 - v1)); uv[j + 2] = meshUV[i + 2]; triangles[j] = j; triangles[j + 1] = j + 1; triangles[j + 2] = j + 2; edges[k] = j; edges[k + 1] = j + 1; k += 2; j += 3; } else if (v0 > 0 && v1 < 0 && v2 <= 0) { vertices[j] = meshVertices[i]; vertices[j + 1] = meshVertices[i + 1] + (meshVertices[i] - meshVertices[i + 1]) * (1 - v0 / (v0 - v1)); vertices[j + 2] = meshVertices[i + 2] + (meshVertices[i] - meshVertices[i + 2]) * (1 - v0 / (v0 - v2)); uv[j] = meshUV[i]; uv[j + 1] = meshUV[i + 1] + (meshUV[i] - meshUV[i + 1]) * (1 - v0 / (v0 - v1)); uv[j + 2] = meshUV[i + 2] + (meshUV[i] - meshUV[i + 2]) * (1 - v0 / (v0 - v2)); triangles[j] = j; triangles[j + 1] = j + 1; triangles[j + 2] = j + 2; edges[k] = j + 1; edges[k + 1] = j + 2; k += 2; j += 3; } else if (v0 < 0 && v1 > 0 && v2 <= 0) { vertices[j] = meshVertices[i] + (meshVertices[i + 1] - meshVertices[i]) * (1 - v1 / (v1 - v0)); vertices[j + 1] = meshVertices[i + 1]; vertices[j + 2] = meshVertices[i + 2] + (meshVertices[i + 1] - meshVertices[i + 2]) * (1 - v1 / (v1 - v2)); uv[j] = meshUV[i] + (meshUV[i + 1] - meshUV[i]) * (1 - v1 / (v1 - v0)); uv[j + 1] = meshUV[i + 1]; uv[j + 2] = meshUV[i + 2] + (meshUV[i + 1] - meshUV[i + 2]) * (1 - v1 / (v1 - v2)); triangles[j] = j; triangles[j + 1] = j + 1; triangles[j + 2] = j + 2; edges[k] = j; edges[k + 1] = j + 2; k += 2; j += 3; } else if (v0 < 0 && v1 <= 0 && v2 > 0) { vertices[j] = meshVertices[i] + (meshVertices[i + 2] - meshVertices[i]) * (1 - v2 / (v2 - v0)); vertices[j + 1] = meshVertices[i + 1] + (meshVertices[i + 2] - meshVertices[i + 1]) * (1 - v2 / (v2 - v1)); vertices[j + 2] = meshVertices[i + 2]; uv[j] = meshUV[i] + (meshUV[i + 2] - meshUV[i]) * (1 - v2 / (v2 - v0)); uv[j + 1] = meshUV[i + 1] + (meshUV[i + 2] - meshUV[i + 1]) * (1 - v2 / (v2 - v1)); uv[j + 2] = meshUV[i + 2]; triangles[j] = j; triangles[j + 1] = j + 1; triangles[j + 2] = j + 2; edges[k] = j; edges[k + 1] = j + 1; k += 2; j += 3; } else if (v0 < 0 && v1 > 0 && v2 > 0) { vertices[j] = meshVertices[i] + (meshVertices[i + 1] - meshVertices[i]) * (1 - v1 / (v1 - v0)); vertices[j + 1] = meshVertices[i + 1]; vertices[j + 2] = meshVertices[i + 2]; uv[j] = meshUV[i] + (meshUV[i + 1] - meshUV[i]) * (1 - v1 / (v1 - v0)); uv[j + 1] = meshUV[i + 1]; uv[j + 2] = meshUV[i + 2]; triangles[j] = j; triangles[j + 1] = j + 1; triangles[j + 2] = j + 2; j += 3; vertices[j] = meshVertices[i] + (meshVertices[i + 1] - meshVertices[i]) * (1 - v1 / (v1 - v0)); vertices[j + 1] = meshVertices[i + 2]; vertices[j + 2] = meshVertices[i] + (meshVertices[i + 2] - meshVertices[i]) * (1 - v2 / (v2 - v0)); uv[j] = meshUV[i] + (meshUV[i + 1] - meshUV[i]) * (1 - v1 / (v1 - v0)); uv[j + 1] = meshUV[i + 2]; uv[j + 2] = meshUV[i] + (meshUV[i + 2] - meshUV[i]) * (1 - v2 / (v2 - v0)); triangles[j] = j; triangles[j + 1] = j + 1; triangles[j + 2] = j + 2; edges[k] = j; edges[k + 1] = j + 2; k += 2; j += 3; } else if (v0 > 0 && v1 < 0 && v2 > 0) { vertices[j] = meshVertices[i]; vertices[j + 1] = meshVertices[i + 1] + (meshVertices[i + 2] - meshVertices[i + 1]) * (1 - v2 / (v2 - v1)); vertices[j + 2] = meshVertices[i + 2]; uv[j] = meshUV[i]; uv[j + 1] = meshUV[i + 1] + (meshUV[i + 2] - meshUV[i + 1]) * (1 - v2 / (v2 - v1)); uv[j + 2] = meshUV[i + 2]; triangles[j] = j; triangles[j + 1] = j + 1; triangles[j + 2] = j + 2; j += 3; vertices[j] = meshVertices[i]; vertices[j + 1] = meshVertices[i + 1] + (meshVertices[i] - meshVertices[i + 1]) * (1 - v0 / (v0 - v1)); vertices[j + 2] = meshVertices[i + 1] + (meshVertices[i + 2] - meshVertices[i + 1]) * (1 - v2 / (v2 - v1)); uv[j] = meshUV[i]; uv[j + 1] = meshUV[i + 1] + (meshUV[i] - meshUV[i + 1]) * (1 - v0 / (v0 - v1)); uv[j + 2] = meshUV[i + 1] + (meshUV[i + 2] - meshUV[i + 1]) * (1 - v2 / (v2 - v1)); triangles[j] = j; triangles[j + 1] = j + 1; triangles[j + 2] = j + 2; edges[k] = j + 1; edges[k + 1] = j + 2; k += 2; j += 3; } else if (v0 > 0 && v1 > 0 && v2 < 0) { vertices[j] = meshVertices[i]; vertices[j + 1] = meshVertices[i + 1]; vertices[j + 2] = meshVertices[i + 2] + (meshVertices[i + 1] - meshVertices[i + 2]) * (1 - v1 / (v1 - v2)); uv[j] = meshUV[i]; uv[j + 1] = meshUV[i + 1]; uv[j + 2] = meshUV[i + 2] + (meshUV[i + 1] - meshUV[i + 2]) * (1 - v1 / (v1 - v2)); triangles[j] = j; triangles[j + 1] = j + 1; triangles[j + 2] = j + 2; j += 3; vertices[j] = meshVertices[i]; vertices[j + 1] = meshVertices[i + 2] + (meshVertices[i + 1] - meshVertices[i + 2]) * (1 - v1 / (v1 - v2)); vertices[j + 2] = meshVertices[i + 2] + (meshVertices[i] - meshVertices[i + 2]) * (1 - v0 / (v0 - v2)); uv[j] = meshUV[i]; uv[j + 1] = meshUV[i + 2] + (meshUV[i + 1] - meshUV[i + 2]) * (1 - v1 / (v1 - v2)); uv[j + 2] = meshUV[i + 2] + (meshUV[i] - meshUV[i + 2]) * (1 - v0 / (v0 - v2)); triangles[j] = j; triangles[j + 1] = j + 1; triangles[j + 2] = j + 2; edges[k] = j + 1; edges[k + 1] = j + 2; k += 2; j += 3; } } } if (cap && edges.Length > 2) { Vector3 edgesAverage = Vector3.zero; for (int i = 0; i < edges.Length; i++) { edgesAverage += vertices[edges[i]] / newEdges; } Vector3 x = (vertices[edges[0]] - edgesAverage).normalized; Vector3 y = Vector3.Cross(plane.normal, x).normalized; int maxIndex = 0; float max = 0; for (int i = 0; i < edges.Length; i++) { if (Vector3.Dot(vertices[edges[i]] - edgesAverage, vertices[edges[i]] - edgesAverage) > max) { max = Vector3.Dot(vertices[edges[i]] - edgesAverage, vertices[edges[i]] - edgesAverage); maxIndex = i; } } max = Vector2.Distance(new Vector2(Vector3.Dot(vertices[edges[maxIndex]], x), Vector3.Dot(vertices[edges[maxIndex]], y)), Vector2.zero); for (int i = 0, j = newTriangles; i < edges.Length; i += 2) { if (Vector3.Dot(meshTransform.TransformDirection(Vector3.Cross(vertices[edges[i]] - edgesAverage, vertices[edges[i + 1]] - edgesAverage)), plane.normal) > 0) { vertices[j] = vertices[edges[i + 1]]; vertices[j + 1] = vertices[edges[i]]; vertices[j + 2] = edgesAverage; uv[j] = new Vector2(Vector3.Dot(vertices[edges[i + 1]], x), Vector3.Dot(vertices[edges[i + 1]], y)) * 0.5f / max + Vector2.one * 0.5f; uv[j + 1] = new Vector2(Vector3.Dot(vertices[edges[i]], x), Vector3.Dot(vertices[edges[i]], y)) * 0.5f / max + Vector2.one * 0.5f; uv[j + 2] = Vector2.one * 0.5f; } else { vertices[j] = vertices[edges[i]]; vertices[j + 1] = vertices[edges[i + 1]]; vertices[j + 2] = edgesAverage; uv[j] = new Vector2(Vector3.Dot(vertices[edges[i]], x), Vector3.Dot(vertices[edges[i]], y)) * 0.5f / max + Vector2.one * 0.5f; uv[j + 1] = new Vector2(Vector3.Dot(vertices[edges[i + 1]], x), Vector3.Dot(vertices[edges[i + 1]], y)) * 0.5f / max + Vector2.one * 0.5f; uv[j + 2] = Vector2.one * 0.5f; } triangles[j] = j; triangles[j + 1] = j + 1; triangles[j + 2] = j + 2; j += 3; } } mesh.Clear(); mesh.vertices = vertices; mesh.uv = uv; mesh.normals = new Vector3[triangles.Length]; mesh.triangles = triangles; mesh.RecalculateNormals(); //Debug Code Start print("SplitMesh total execution time: " + (Time.realtimeSinceStartup - startTime) + " seconds for " + (triangles.Length / 3) + " triangles"); //Debug Code Stop }
void FixedUpdate() { // reset movement state m_movementState = MovementState.NONE; // reset movement Vector m_movementVector = Vector3.zero; // Forward if (Input.GetKey(SingletonManager.GameManager.m_gameControls.forward)) { m_movementVector += Vector3.Normalize(Camera.main.transform.forward); } // Backward if (Input.GetKey(SingletonManager.GameManager.m_gameControls.backward)) { m_movementVector += -Vector3.Normalize(Camera.main.transform.forward); } // Left if (Input.GetKey(SingletonManager.GameManager.m_gameControls.left)) { Vector3 tmp = Vector3.Normalize(Camera.main.transform.forward); m_movementVector += Vector3.Cross(tmp, Vector3.up); } // Right if (Input.GetKey(SingletonManager.GameManager.m_gameControls.right)) { Vector3 tmp = Vector3.Normalize(Camera.main.transform.forward); m_movementVector += -Vector3.Cross(tmp, Vector3.up); } // Debug.DrawLine // XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX // make movementVector with length of 1 m_movementVector.Normalize(); // Update player state UpdatePlayerState(); CanUncrouch(); if (m_movementVector != Vector3.zero) { m_movementVector = m_movementVector * m_movementSpeed * 100.0f * Time.fixedDeltaTime; m_movementVector.y = m_rigidbody.velocity.y; // this needs to be here, else the gravity on y-axis won't take effect on player while moving m_rigidbody.velocity = m_movementVector; } else { // player won't slide anymore m_rigidbody.velocity = new Vector3(0.0f, m_rigidbody.velocity.y, 0.0f); } m_crouchState = m_movementState; }
public void Rotate( ref Vector3 _Axis, double _Angle, out Vector3 _Out ) { double cos_ang = Math.Cos( _Angle ); double sin_ang = Math.Sin( _Angle ); _Out.x = x * cos_ang; _Out.y = y * cos_ang; _Out.z = z * cos_ang; double temp = Dot( ref _Axis ); temp *= 1.0-cos_ang; _Out.x += _Axis.x * temp; _Out.y += _Axis.y * temp; _Out.z += _Axis.z * temp; _Axis.Cross( ref this, out TempCross ); _Out.x += TempCross.x * sin_ang; _Out.y += TempCross.y * sin_ang; _Out.z += TempCross.z * sin_ang; }
public void GenerateMesh(Simulation.TerrainCell[,] cellHeights, Simulation.TerrainManager terMan, Material MeshMaterial) { Vector3 tp = transform.position; int numVerts = (cellHeights.GetLength(0) + 1) * (cellHeights.GetLength(1) + 1) * 6; int numTriangles = (cellHeights.GetLength(0) + 1) * (cellHeights.GetLength(1) + 1) * 6; Vector3[] verts = new Vector3[numVerts]; int[] triangles = new int[numTriangles]; Vector3[] normals = new Vector3[numVerts]; Vector2[] uv = new Vector2[numVerts]; int counter = 0; for (int i = 0; i < cellHeights.GetLength(0); i++) { for (int j = 0; j < cellHeights.GetLength(1); j++) { float cellHeight = 0; // cellHeights[i, j].GetHeight(); float downCell = 0, upCell = 0, rightCell = 0, leftCell = 0; float downRightCell = 0, downLeftCell = 0, upRightCell = 0, upLeftCell = 0; if (i == 0 || i == cellHeights.GetLength(0) - 1 || j == 0 || j == cellHeights.GetLength(1) - 1) { //downCell = terMan.GetHeightAtCell(i + 1 + tp.x, j + tp.z); //upCell = terMan.GetHeightAtCell(i - 1 + tp.x, j + tp.z); //rightCell = terMan.GetHeightAtCell(i + tp.x, j + 1 + tp.z); //leftCell = terMan.GetHeightAtCell(i + tp.x, j - 1 + tp.z); // //downRightCell = terMan.GetHeightAtCell(i + 1 + tp.x, j + 1 + tp.z); //downLeftCell = terMan.GetHeightAtCell(i + 1 + tp.x, j - 1 + tp.z); //upRightCell = terMan.GetHeightAtCell(i - 1 + tp.x, j + 1 + tp.z); //upLeftCell = terMan.GetHeightAtCell(i - 1 + tp.x, j - 1 + tp.z); } else { //downCell = cellHeights[i + 1, j].GetHeight(); //upCell = cellHeights[i - 1, j].GetHeight(); //rightCell = cellHeights[i, j + 1].GetHeight(); //leftCell = cellHeights[i, j - 1].GetHeight(); // //downRightCell = cellHeights[i + 1, j + 1].GetHeight(); //downLeftCell = cellHeights[i + 1, j - 1].GetHeight(); //upRightCell = cellHeights[i - 1, j + 1].GetHeight(); //upLeftCell = cellHeights[i - 1, j - 1].GetHeight(); } float topRightCorner = Mathf.Max(cellHeight, downCell, rightCell, downRightCell);; float topLeftCorner = Mathf.Max(cellHeight, downCell, leftCell, downLeftCell); float bottomRightCorner = Mathf.Max(cellHeight, upCell, rightCell, upRightCell);; float bottomLeftCorner = Mathf.Max(cellHeight, upCell, leftCell, upLeftCell);; if (topRightCorner == bottomLeftCorner) { verts[counter] = new Vector3(i, bottomLeftCorner, j); verts[counter + 1] = new Vector3(i, bottomRightCorner, j + 1); verts[counter + 2] = new Vector3(i + 1, topRightCorner, j + 1); verts[counter + 3] = new Vector3(i, bottomLeftCorner, j); verts[counter + 4] = new Vector3(i + 1, topRightCorner, j + 1); verts[counter + 5] = new Vector3(i + 1, topLeftCorner, j); Vector3 bL = new Vector3(i, bottomLeftCorner, j); Vector3 bR = new Vector3(i, bottomRightCorner, j + 1); Vector3 tL = new Vector3(i + 1, topLeftCorner, j); Vector3 tR = new Vector3(i + 1, topRightCorner, j + 1); Vector3 upperCross = Vector3.Cross(tR - bR, bL - bR).normalized; Vector3 lowerCross = Vector3.Cross(bL - tL, tR - tL).normalized; normals[counter] = normals[counter + 1] = normals[counter + 2] = upperCross; normals[counter + 3] = normals[counter + 4] = normals[counter + 5] = lowerCross; uv[counter] = new Vector2(i, j); uv[counter + 1] = new Vector2(i, j + 1); uv[counter + 2] = new Vector2(i + 1, j + 1); uv[counter + 3] = new Vector2(i, j); uv[counter + 4] = new Vector2(i + 1, j + 1); uv[counter + 5] = new Vector2(i + 1, j); } else { verts[counter] = new Vector3(i, bottomLeftCorner, j); verts[counter + 1] = new Vector3(i, bottomRightCorner, j + 1); verts[counter + 2] = new Vector3(i + 1, topLeftCorner, j); verts[counter + 3] = new Vector3(i, bottomRightCorner, j + 1); verts[counter + 4] = new Vector3(i + 1, topRightCorner, j + 1); verts[counter + 5] = new Vector3(i + 1, topLeftCorner, j); Vector3 bL = new Vector3(i, bottomLeftCorner, j); Vector3 bR = new Vector3(i, bottomRightCorner, j + 1); Vector3 tL = new Vector3(i + 1, topLeftCorner, j); Vector3 tR = new Vector3(i + 1, topRightCorner, j + 1); Vector3 upperCross = Vector3.Cross(tL - tR, bR - tR).normalized; Vector3 lowerCross = Vector3.Cross(bR - bL, tL - bL).normalized; normals[counter] = normals[counter + 1] = normals[counter + 2] = lowerCross; normals[counter + 3] = normals[counter + 4] = normals[counter + 5] = upperCross; uv[counter] = new Vector2(i, j); uv[counter + 1] = new Vector2(i, j + 1); uv[counter + 2] = new Vector2(i + 1, j); uv[counter + 3] = new Vector2(i, j + 1); uv[counter + 4] = new Vector2(i + 1, j + 1); uv[counter + 5] = new Vector2(i + 1, j); } counter += 6; } } for (int i = 0; i < (cellHeights.GetLength(0) + 1) * (cellHeights.GetLength(1) + 1) * 6; i++) { triangles[i] = i; //no vertex saving, each triangle gets its own three vertices, in order } mesh = new Mesh(); mesh.name = "Chunk Mesh"; mesh.vertices = verts; mesh.triangles = triangles; mesh.normals = normals; mesh.uv = uv; GetComponent <MeshFilter>().mesh = mesh; GetComponent <MeshRenderer>().material = MeshMaterial; GetComponent <MeshCollider>().sharedMesh = mesh; //OptemizeMesh(mesh, MeshMaterial); }
void timer_Tick(object sender, EventArgs e) { Vector3 to = _Camera._Target - _Camera._Position; to.Normalise(); Vector3 up = new Vector3(0, 1, 0); Vector3 right = up.Cross(to); right.Normalise(); Vector3 newup = to.Cross(right); newup.Normalise(); right.Mul(_Velocity.x); to.Mul(_Velocity.z); newup.Mul(_Velocity.y); // if (!Keyboard.IsKeyDown(Key.LeftShift) && !Keyboard.IsKeyDown(Key.RightShift)) { _Camera._Position.Add(right); _Camera._Position.Add(to); _Camera._Position.Add(newup); _Camera._Target.Add(right); _Camera._Target.Add(to); _Camera._Target.Add(newup); } /* else { _Camera._Position.Add(right); _Camera._Position.Add(newup); } */ _WootracerOptions.UpdateGUI(); _WootracerOptions._FocusDistance = (_Camera._Target - _Camera._Position).Magnitude(); _Camera._FOV = _WootracerOptions._FieldOfView; _Camera._Spherical = _WootracerOptions._Spherical; _Camera._Stereographic = _WootracerOptions._Stereographic; _Velocity *= 0.6; _ImageRenderer._RampValue = 1;// _ImageRenderer._MaxValue; _ImageRenderer.TransferLatest(false); if (_Dirty || _CameraDirty || _Velocity.MagnitudeSquared() > 0.0001 && _ImageRenderer != null) { _ImageRenderer.Stop(); if (_Dirty) { Compile(); } else { Compile(); // _ImageRenderer.UpdateCamera(_Camera.CreateElement().ToString()); } _ImageRenderer.Render(); } // if (_Velocity.MagnitudeSquared() < 0.0001) // _Timer.Stop(); }
// Token: 0x06008627 RID: 34343 RVA: 0x003466A0 File Offset: 0x00344AA0 public void EyeUpdateCalc(Vector3 target, int ptnNo) { if (!this.initEnd) { if (this.targetObj != null && this.targetObj.activeSelf) { this.targetObj.SetActive(false); } return; } this.nowPtnNo = ptnNo; if (!EyeLookCalc.isEnabled) { if (this.targetObj != null && this.targetObj.activeSelf) { this.targetObj.SetActive(false); } return; } if (Time.deltaTime == 0f) { if (this.targetObj != null && this.targetObj.activeSelf) { this.targetObj.SetActive(false); } return; } EyeTypeState eyeTypeState = this.eyeTypeStates[ptnNo]; EYE_LOOK_TYPE eye_LOOK_TYPE = this.eyeTypeStates[ptnNo].lookType; if (eye_LOOK_TYPE == EYE_LOOK_TYPE.NO_LOOK) { this.eyeObjs[0].eyeTransform.localRotation = this.fixAngle[0]; this.eyeObjs[1].eyeTransform.localRotation = this.fixAngle[1]; if (this.targetObj != null && this.targetObj.activeSelf) { this.targetObj.SetActive(false); } return; } Vector3 position = this.rootNode.InverseTransformPoint(target); float magnitude = position.magnitude; if (magnitude < this.eyeTypeStates[ptnNo].nearDis) { position = position.normalized * this.eyeTypeStates[ptnNo].nearDis; target = this.rootNode.TransformPoint(position); } Vector3 vector = new Vector3(position.x, 0f, position.z); float num = Vector3.Dot(vector, Vector3.forward); float num2 = Vector3.Angle(vector, Vector3.forward); vector = new Vector3(0f, position.y, position.z); float num3 = Vector3.Dot(vector, Vector3.forward); float num4 = Vector3.Angle(vector, Vector3.forward); if (num < 0f || num3 < 0f || num2 > this.eyeTypeStates[ptnNo].hAngleLimit || num4 > this.eyeTypeStates[ptnNo].vAngleLimit) { eye_LOOK_TYPE = EYE_LOOK_TYPE.FORWARD; } if (eye_LOOK_TYPE == EYE_LOOK_TYPE.FORWARD) { target = this.rootNode.position + this.rootNode.forward * this.eyeTypeStates[ptnNo].forntTagDis; } if (eye_LOOK_TYPE == EYE_LOOK_TYPE.CONTROL || this.eyeTypeStates[ptnNo].lookType == EYE_LOOK_TYPE.CONTROL) { if (this.targetObj != null) { if (!this.targetObj.activeSelf) { this.targetObj.SetActive(true); } target = Vector3.MoveTowards(this.rootNode.transform.position, this.targetObj.transform.position, this.eyeTypeStates[ptnNo].forntTagDis); this.targetObj.transform.position = Vector3.MoveTowards(this.rootNode.transform.position, target, 0.5f); } } else if (this.targetObj != null) { this.targetObj.transform.position = Vector3.MoveTowards(this.rootNode.transform.position, target, 0.5f); if (this.targetObj.activeSelf) { this.targetObj.SetActive(false); } } float num5 = -1f; foreach (EyeObject eyeObject in this.eyeObjs) { eyeObject.eyeTransform.localRotation = eyeObject.origRotation; Quaternion rotation = eyeObject.eyeTransform.parent.rotation; Quaternion rotation2 = Quaternion.Inverse(rotation); Vector3 normalized = (target - eyeObject.eyeTransform.position).normalized; Vector3 vector2 = rotation2 * normalized; float num6 = EyeLookCalc.AngleAroundAxis(eyeObject.referenceLookDir, vector2, eyeObject.referenceUpDir); Vector3 axis = Vector3.Cross(eyeObject.referenceUpDir, vector2); Vector3 dirA = vector2 - Vector3.Project(vector2, eyeObject.referenceUpDir); float num7 = EyeLookCalc.AngleAroundAxis(dirA, vector2, axis); float f = Mathf.Max(0f, Mathf.Abs(num6) - eyeTypeState.thresholdAngleDifference) * Mathf.Sign(num6); float f2 = Mathf.Max(0f, Mathf.Abs(num7) - eyeTypeState.thresholdAngleDifference) * Mathf.Sign(num7); num6 = Mathf.Max(Mathf.Abs(f) * Mathf.Abs(eyeTypeState.bendingMultiplier), Mathf.Abs(num6) - eyeTypeState.maxAngleDifference) * Mathf.Sign(num6) * Mathf.Sign(eyeTypeState.bendingMultiplier); num7 = Mathf.Max(Mathf.Abs(f2) * Mathf.Abs(eyeTypeState.bendingMultiplier), Mathf.Abs(num7) - eyeTypeState.maxAngleDifference) * Mathf.Sign(num7) * Mathf.Sign(eyeTypeState.bendingMultiplier); float max = eyeTypeState.maxBendingAngle; float min = eyeTypeState.minBendingAngle; if (eyeObject.eyeLR == EYE_LR.EYE_R) { max = -eyeTypeState.minBendingAngle; min = -eyeTypeState.maxBendingAngle; } num6 = Mathf.Clamp(num6, min, max); num7 = Mathf.Clamp(num7, eyeTypeState.upBendingAngle, eyeTypeState.downBendingAngle); Vector3 axis2 = Vector3.Cross(eyeObject.referenceUpDir, eyeObject.referenceLookDir); if (eye_LOOK_TYPE == EYE_LOOK_TYPE.AWAY) { if (num5 == -1f) { float num8 = Mathf.Lerp(-1f, 1f, Mathf.InverseLerp(-this.eyeTypeStates[this.nowPtnNo].maxBendingAngle, -this.eyeTypeStates[this.nowPtnNo].minBendingAngle, eyeObject.angleH)); float num9 = Mathf.Lerp(-1f, 1f, Mathf.InverseLerp(-this.eyeTypeStates[this.nowPtnNo].maxBendingAngle, -this.eyeTypeStates[this.nowPtnNo].minBendingAngle, num6)); float num10 = num8 - num9; if (Mathf.Abs(num10) < this.sorasiRate) { if (num10 < 0f) { if (num9 < -this.sorasiRate) { num8 = num9 + this.sorasiRate; } else { num8 = num9 - this.sorasiRate; } } else if (num10 > 0f) { if (num9 > this.sorasiRate) { num8 = num9 - this.sorasiRate; } else { num8 = num9 + this.sorasiRate; } } else { num8 = num9 + this.sorasiRate; } num5 = Mathf.InverseLerp(-1f, 1f, num8); num6 = Mathf.Lerp(-this.eyeTypeStates[this.nowPtnNo].maxBendingAngle, -this.eyeTypeStates[this.nowPtnNo].minBendingAngle, num5); } else { num5 = Mathf.InverseLerp(-1f, 1f, num8); num6 = eyeObject.angleH; } } else { num6 = Mathf.Lerp(-this.eyeTypeStates[this.nowPtnNo].maxBendingAngle, -this.eyeTypeStates[this.nowPtnNo].minBendingAngle, num5); } num7 = -num7; } eyeObject.angleH = Mathf.Lerp(eyeObject.angleH, num6, Time.deltaTime * eyeTypeState.leapSpeed); eyeObject.angleV = Mathf.Lerp(eyeObject.angleV, num7, Time.deltaTime * eyeTypeState.leapSpeed); vector2 = Quaternion.AngleAxis(eyeObject.angleH, eyeObject.referenceUpDir) * Quaternion.AngleAxis(eyeObject.angleV, axis2) * eyeObject.referenceLookDir; Vector3 referenceUpDir = eyeObject.referenceUpDir; Vector3.OrthoNormalize(ref vector2, ref referenceUpDir); Vector3 forward = vector2; eyeObject.dirUp = Vector3.Slerp(eyeObject.dirUp, referenceUpDir, Time.deltaTime * 5f); Vector3.OrthoNormalize(ref forward, ref eyeObject.dirUp); Quaternion lhs = rotation * Quaternion.LookRotation(forward, eyeObject.dirUp) * Quaternion.Inverse(rotation * Quaternion.LookRotation(eyeObject.referenceLookDir, eyeObject.referenceUpDir)); eyeObject.eyeTransform.rotation = lhs * eyeObject.eyeTransform.rotation; } this.targetPos = target; this.fixAngle[0] = this.eyeObjs[0].eyeTransform.localRotation; this.fixAngle[1] = this.eyeObjs[1].eyeTransform.localRotation; this.AngleHRateCalc(); this.angleVRate = this.AngleVRateCalc(); }
/// <summary> /// /// </summary> /// <param name="quat"></param> /// <param name="vector"></param> /// <returns></returns> public static Vector3 operator *( Quaternion quat, Vector3 vector ) { // nVidia SDK implementation Vector3 uv, uuv; var qvec = new Vector3( quat.x, quat.y, quat.z ); uv = qvec.Cross( vector ); uuv = qvec.Cross( uv ); uv *= ( 2.0f*quat.w ); uuv *= 2.0f; return vector + uv + uuv; // get the rotation matrix of the Quaternion and multiply it times the vector //return quat.ToRotationMatrix() * vector; }
/// <summary> /// /// </summary> /// <param name="name"></param> /// <param name="plane"></param> /// <param name="width"></param> /// <param name="height"></param> /// <param name="curvature"></param> /// <param name="xSegments"></param> /// <param name="ySegments"></param> /// <param name="normals"></param> /// <param name="numberOfTexCoordSets"></param> /// <param name="uTiles"></param> /// <param name="vTiles"></param> /// <param name="upVector"></param> /// <param name="orientation"></param> /// <param name="vertexBufferUsage"></param> /// <param name="indexBufferUsage"></param> /// <param name="vertexShadowBuffer"></param> /// <param name="indexShadowBuffer"></param> /// <returns></returns> public Mesh CreateCurvedIllusionPlane(string name, Plane plane, float width, float height, float curvature, int xSegments, int ySegments, bool normals, int numberOfTexCoordSets, float uTiles, float vTiles, Vector3 upVector, Quaternion orientation, BufferUsage vertexBufferUsage, BufferUsage indexBufferUsage, bool vertexShadowBuffer, bool indexShadowBuffer) { Mesh mesh = CreateManual(name); SubMesh subMesh = mesh.CreateSubMesh(name + "SubMesh"); // set up vertex data, use a single shared buffer mesh.SharedVertexData = new VertexData(); VertexData vertexData = mesh.SharedVertexData; // set up vertex declaration VertexDeclaration vertexDeclaration = vertexData.vertexDeclaration; int currentOffset = 0; // always need positions vertexDeclaration.AddElement(0, currentOffset, VertexElementType.Float3, VertexElementSemantic.Position); currentOffset += VertexElement.GetTypeSize(VertexElementType.Float3); // optional normals if(normals) { vertexDeclaration.AddElement(0, currentOffset, VertexElementType.Float3, VertexElementSemantic.Normal); currentOffset += VertexElement.GetTypeSize(VertexElementType.Float3); } for(ushort i = 0; i < numberOfTexCoordSets; i++) { // assumes 2d texture coordinates vertexDeclaration.AddElement(0, currentOffset, VertexElementType.Float2, VertexElementSemantic.TexCoords, i); currentOffset += VertexElement.GetTypeSize(VertexElementType.Float2); } vertexData.vertexCount = (xSegments + 1) * (ySegments + 1); // allocate vertex buffer HardwareVertexBuffer vertexBuffer = HardwareBufferManager.Instance.CreateVertexBuffer(vertexDeclaration.GetVertexSize(0), vertexData.vertexCount, vertexBufferUsage, vertexShadowBuffer); // set up the binding, one source only VertexBufferBinding binding = vertexData.vertexBufferBinding; binding.SetBinding(0, vertexBuffer); // work out the transform required, default orientation of plane is normal along +z, distance 0 Matrix4 xlate, xform, rot; Matrix3 rot3 = Matrix3.Identity; xlate = rot = Matrix4.Identity; // determine axes Vector3 zAxis, yAxis, xAxis; zAxis = plane.Normal; zAxis.Normalize(); yAxis = upVector; yAxis.Normalize(); xAxis = yAxis.Cross(zAxis); if(xAxis.Length == 0) { throw new AxiomException("The up vector for a plane cannot be parallel to the planes normal."); } rot3.FromAxes(xAxis, yAxis, zAxis); rot = rot3; // set up standard xform from origin xlate.Translation = plane.Normal * -plane.D; // concatenate xform = xlate * rot; // generate vertex data, imagine a large sphere with the camera located near the top, // the lower the curvature, the larger the sphere. use the angle from the viewer to the // points on the plane float cameraPosition; // camera position relative to the sphere center // derive sphere radius (unused) //float sphereDistance; // distance from the camera to the sphere along box vertex vector float sphereRadius; // actual values irrelevant, it's the relation between the sphere's radius and the camera's position which is important float SPHERE_RADIUS = 100; float CAMERA_DISTANCE = 5; sphereRadius = SPHERE_RADIUS - curvature; cameraPosition = sphereRadius - CAMERA_DISTANCE; // lock the whole buffer float xSpace = width / xSegments; float ySpace = height / ySegments; float halfWidth = width / 2; float halfHeight = height / 2; Vector3 vec = Vector3.Zero; Vector3 norm = Vector3.Zero; Vector3 min = Vector3.Zero; Vector3 max = Vector3.Zero; float maxSquaredLength = 0; bool firstTime = true; // generate vertex data GenerateCurvedIllusionPlaneVertexData(vertexBuffer, ySegments, xSegments, xSpace, halfWidth, ySpace, halfHeight, xform, firstTime, normals, orientation, cameraPosition, sphereRadius, uTiles, vTiles, numberOfTexCoordSets, ref min, ref max, ref maxSquaredLength); // generate face list subMesh.useSharedVertices = true; Tesselate2DMesh(subMesh, xSegments + 1, ySegments + 1, false, indexBufferUsage, indexShadowBuffer); // generate bounds for the mesh mesh.BoundingBox = new AxisAlignedBox(min, max); mesh.BoundingSphereRadius = MathUtil.Sqrt(maxSquaredLength); mesh.Load(); mesh.Touch(); return mesh; }
/// <summary> /// Gets the shortest arc quaternion to rotate this vector to the destination vector. /// </summary> /// <remarks> /// Don't call this if you think the dest vector can be close to the inverse /// of this vector, since then ANY axis of rotation is ok. /// </remarks> public Quaternion GetRotationTo(Vector3 destination) { // Based on Stan Melax's article in Game Programming Gems Quaternion q = new Quaternion(); Vector3 v0 = new Vector3(this.x, this.y, this.z); Vector3 v1 = destination; // normalize both vectors v0.Normalize(); v1.Normalize(); // get the cross product of the vectors Vector3 c = v0.Cross(v1); // If the cross product approaches zero, we get unstable because ANY axis will do // when v0 == -v1 float d = v0.Dot(v1); // If dot == 1, vectors are the same if (d >= 1.0f) { return Quaternion.Identity; } float s = MathUtil.Sqrt( (1+d) * 2 ); float inverse = 1 / s; q.x = c.x * inverse; q.y = c.y * inverse; q.z = c.z * inverse; q.w = s * 0.5f; return q; }
/// Multiply a Vector3. public static Vector3 operator *(Quaternion lhs, Vector3 rhs) { Vector3 qVec = new Vector3(lhs.x_, lhs.y_, lhs.z_); Vector3 cross1 = qVec.Cross(rhs); Vector3 cross2 = qVec.Cross(cross1); return rhs + (cross1 * lhs.w_ + cross2) * 2.0f; }
/// <summary> /// 2つのベクトルがなす角をかえす /// </summary> /// <param name="vecA"></param> /// <param name="vecB"></param> /// <returns></returns> public double VecToRad(Vector3 vecA, Vector3 vecB) { vecA.Normalize(); vecB.Normalize(); double rad = vecA.Dot(vecB); if (rad > 1.0) rad = 1.0; double dir = (double)(Math.Asin(rad) - (Math.PI / 2.0)); if (double.IsNaN(dir)) { Debug.Write("NAn"); } Vector3 resVec = vecA.Cross(vecB); if (resVec.z > 0) dir = -dir; return dir; }
public Vector3 GetTorque(Vector3 thrust) { return(-Vector3.Cross(pos, thrust)); }
/// <summary> /// /// </summary> /// <param name="name">Name of the plane mesh.</param> /// <param name="plane">Plane to use for distance and orientation of the mesh.</param> /// <param name="width">Width in world coordinates.</param> /// <param name="height">Height in world coordinates.</param> /// <param name="xSegments">Number of x segments for tesselation.</param> /// <param name="ySegments">Number of y segments for tesselation.</param> /// <param name="normals">If true, plane normals are created.</param> /// <param name="numTexCoordSets">Number of 2d texture coord sets to use.</param> /// <param name="uTile">Number of times the texture should be repeated in the u direction.</param> /// <param name="vTile">Number of times the texture should be repeated in the v direction.</param> /// <param name="upVec">The up direction of the plane.</param> /// <returns></returns> public Mesh CreatePlane(string name, Plane plane, float width, float height, int xSegments, int ySegments, bool normals, int numTexCoordSets, float uTile, float vTile, Vector3 upVec, BufferUsage vertexBufferUsage, BufferUsage indexBufferUsage, bool vertexShadowBuffer, bool indexShadowBuffer ) { Mesh mesh = CreateManual(name); SubMesh subMesh = mesh.CreateSubMesh(name + "SubMesh"); mesh.SharedVertexData = new VertexData(); VertexData vertexData = mesh.SharedVertexData; VertexDeclaration decl = vertexData.vertexDeclaration; int currOffset = 0; // add position data decl.AddElement(0, currOffset, VertexElementType.Float3, VertexElementSemantic.Position); currOffset += VertexElement.GetTypeSize(VertexElementType.Float3); // normals are optional if(normals) { decl.AddElement(0, currOffset, VertexElementType.Float3, VertexElementSemantic.Normal); currOffset += VertexElement.GetTypeSize(VertexElementType.Float3); } // add texture coords for(ushort i = 0; i < numTexCoordSets; i++) { decl.AddElement(0, currOffset, VertexElementType.Float2, VertexElementSemantic.TexCoords, i); currOffset += VertexElement.GetTypeSize(VertexElementType.Float2); } vertexData.vertexCount = (xSegments + 1) * (ySegments + 1); // create a new vertex buffer (based on current API) HardwareVertexBuffer vbuf = HardwareBufferManager.Instance.CreateVertexBuffer(decl.GetVertexSize(0), vertexData.vertexCount, vertexBufferUsage, vertexShadowBuffer); // get a reference to the vertex buffer binding VertexBufferBinding binding = vertexData.vertexBufferBinding; // bind the first vertex buffer binding.SetBinding(0, vbuf); // transform the plane based on its plane def Matrix4 translate = Matrix4.Identity; Matrix4 transform = Matrix4.Zero; Matrix4 rotation = Matrix4.Identity; Matrix3 rot3x3 = Matrix3.Zero; Vector3 xAxis, yAxis, zAxis; zAxis = plane.Normal; zAxis.Normalize(); yAxis = upVec; yAxis.Normalize(); xAxis = yAxis.Cross(zAxis); if (xAxis.Length == 0) { throw new AxiomException("The up vector for a plane cannot be parallel to the planes normal."); } rot3x3.FromAxes(xAxis, yAxis, zAxis); rotation = rot3x3; // set up transform from origin translate.Translation = plane.Normal * -plane.D; transform = translate * rotation; float xSpace = width / xSegments; float ySpace = height / ySegments; float halfWidth = width / 2; float halfHeight = height / 2; float xTexCoord = (1.0f * uTile) / xSegments; float yTexCoord = (1.0f * vTile) / ySegments; Vector3 vec = Vector3.Zero; Vector3 min = Vector3.Zero; Vector3 max = Vector3.Zero; float maxSquaredLength = 0; bool firstTime = true; // generate vertex data GeneratePlaneVertexData(vbuf, ySegments, xSegments, xSpace, halfWidth, ySpace, halfHeight, transform, firstTime, normals, rotation, numTexCoordSets, xTexCoord, yTexCoord, subMesh, ref min, ref max, ref maxSquaredLength); // generate face list Tesselate2DMesh(subMesh, xSegments + 1, ySegments + 1, false, indexBufferUsage, indexShadowBuffer); // generate bounds for the mesh mesh.BoundingBox = new AxisAlignedBox(min, max); mesh.BoundingSphereRadius = MathUtil.Sqrt(maxSquaredLength); mesh.Load(); mesh.Touch(); return mesh; }
/// <summary> /// Draws all the particles in a cloud. The cloud system must be initialized, and its projection matrix must be set /// before this is called. /// The texture used to draw the particles is specified by cloud.Texture. /// </summary> /// <param name="cloud">The particle cloud to render.</param> /// <param name="world">The world matrix, indicating the position, rotation, and scale of the particle cloud.</param> /// <param name="view">The view matrix, indicating the camera's current point of view.</param> public void DrawParticleCloud(ParticleCloud cloud, Matrix world, Matrix view) { // Verify that we have been properly initialized. Debug.Assert(isInitialized, "ParticleCloudSystem has not been initialized. " + "You must call Initialize() before it can draw anything."); Debug.Assert(isProjectionMatrixSet, "ParticleCloudSystem has not been given a projection matrix. " + "You must write to Projection before it can draw anything."); // Remember if ZWrite was enabled. bool wasZWriteEnabled = device.RenderState.DepthBufferWriteEnable; // Get the number of particles to draw int numParticles = cloud.NumberOfParticles; // If there is nothing to draw, just skip right now. if (numParticles == 0) { return; } // How many render calls must be use to draw these particles? int numRenders = 1 + numParticles / (MaxParticlesPerRender + 1); // Set the correct effect technique if (cloud.DepthMapRendering) { particleEffect.CurrentTechnique = depthTechnique; } else { particleEffect.CurrentTechnique = cloud.SortingEnabled ? sortedTechnique : unsortedTechnique; } // Set vertex and index stuff device.VertexDeclaration = vertexDeclaration; device.Vertices[0].SetSource(vertexBuffer, 0, ParticleCloudVertex.SizeInBytes); device.Indices = indexBuffer; // Assign shader uniforms if (obsoleteProjection) { projectionParam.SetValue(projection); obsoleteProjection = false; } Matrix worldView = world * view; worldParam.SetValue(world); worldViewParam.SetValue(worldView); textureParam.SetValue(cloud.Texture); Vector3 right = Vector3.Right; Vector3 up = Vector3.Up; // Are the particle billboards axis-aligned? if (cloud.AxisEnabled) { // Get the forward vector from the view matrix. Remember that the view matrix's rotation is // inverted, so we cannot use view.Forward. Vector3 forward = new Vector3(view.M13, view.M23, view.M33); right = Vector3.Cross(forward, cloud.Axis); right.Normalize(); up = cloud.Axis; Vector3.TransformNormal(ref right, ref view, out right); Vector3.TransformNormal(ref up, ref view, out up); } // Scale the right and up vectors according to the X-scale of the WorldView matrix // Billboards cannot be scaled non-uniformly, so we have to assume that it is a uniform scale float sizeScale = worldView.Right.Length(); right = right * sizeScale; up = up * sizeScale; // Sends the vectors to the shader billboardRightParam.SetValue(right); billboardUpParam.SetValue(up); // Start rendering the particles particleEffect.Begin(); for (int i = 0; i < particleEffect.CurrentTechnique.Passes.Count; i++) { EffectPass pass = particleEffect.CurrentTechnique.Passes[i]; for (int renderN = 0; renderN < numRenders; renderN++) { // Calculate the number of particles to render in this render call int numParticlesToRender = numParticles - renderN * MaxParticlesPerRender; if (numParticlesToRender > MaxParticlesPerRender) { numParticlesToRender = MaxParticlesPerRender; } // Get the array start and end indices int arrayStart = renderN * MaxParticlesPerRender; int arrayEnd = arrayStart + numParticlesToRender - 1; // Assign the parameters accordingly if (renderN == 0) { // The first render pass can use the arrays directly. No need to waste time setting up the buffers. positionsParam.SetValue(cloud.Positions); colorsParam.SetValue(cloud.Colors); orientationsParam.SetValue(cloud.Orientations); } else { // We need to construct a new array where the next 80 particles are first in the array. PrepareParticleBuffers(cloud, renderN); positionsParam.SetValue(positionBuffer); colorsParam.SetValue(colorBuffer); orientationsParam.SetValue(orientationBuffer); } pass.Begin(); device.DrawIndexedPrimitives( PrimitiveType.TriangleList, 0, 0, 4 * numParticlesToRender, 0, 2 * numParticlesToRender); pass.End(); } } particleEffect.End(); // It seems that ZWriteEnable propagates to other drawing calls in XNA, so we better clean up // after ourselves. if (cloud.SortingEnabled && wasZWriteEnabled) { device.RenderState.DepthBufferWriteEnable = true; } }
private void walkingUpdate(bool didHit, RaycastHit hit, Vector3 position) { if (didHit) { var legExtensionTimingModifier = walkingLegExtensionTimingModifier; var stepPace = walkingStepPace; if (currentAnimationState == AnimationState.Running) { stepPace = runningStepPace; legExtensionTimingModifier = runningLegExtensionTimingModifier; } currentStepTime += Time.deltaTime; bool extendLeg = false; if (currentStepTime > stepPace) { currentStepTime = 0.0f; stepWithLeftLeg = !stepWithLeftLeg; extendLeg = false; } else if (currentStepTime > stepPace * legExtensionTimingModifier) { extendLeg = true; } Vector3 forwardRotationVector = Vector3.Cross(forwardFacingTargetVector, Vector3.up); if (stepWithLeftLeg) { //Step forward With left leg leftThigh.AddRelativeTorque(Vector3.right * legStrength); //If on forward up swing of leg, bend the knee, otherwise we relax it to extend the leg and finish the forward step if (!extendLeg) { leftKnee.AddRelativeTorque(-Vector3.right * legStrength * 0.5f); } //Contract foot inward leftFoot.AddRelativeTorque(Vector3.right * legStrength * 0.25f); //extend and swing leg back rightThigh.AddRelativeTorque(-Vector3.right * legStrength * legBackSwingModifier); //keep knee extended out rightKnee.AddRelativeTorque(Vector3.right * legStrength * legBackSwingModifier); //Extend foot out rightFoot.AddRelativeTorque(-Vector3.right * legStrength * legBackSwingModifier); //Swing opposite Arm forward rightArm.AddRelativeTorque(-Vector3.forward * armAnimStrength); rightForeArm.AddRelativeTorque(-Vector3.forward * armAnimStrength * 2f); rightForeArm.AddForce(Vector3.up * armAnimStrength); } else { //Step With right leg rightThigh.AddRelativeTorque(Vector3.right * legStrength); //If on forward up swing of leg, bend the knee, otherwise we relax it to extend the leg and finish the forward step if (!extendLeg) { rightKnee.AddRelativeTorque(-Vector3.right * legStrength * 0.5f); } //Contract foot inward rightFoot.AddRelativeTorque(Vector3.right * legStrength * 0.25f); //extend and swing leg back leftThigh.AddRelativeTorque(-Vector3.right * legStrength * legBackSwingModifier); //keep knee extended out leftKnee.AddRelativeTorque(Vector3.right * legStrength * legBackSwingModifier); //Extend foot out leftFoot.AddRelativeTorque(-Vector3.right * legStrength * legBackSwingModifier); //Swing opposite Arm forward leftArm.AddRelativeTorque(-Vector3.forward * armAnimStrength); leftForeArm.AddRelativeTorque(-Vector3.forward * armAnimStrength * 2f); leftForeArm.AddForce(Vector3.up * armAnimStrength); } Debug.Log(leftFoot.velocity); Debug.Log(rightFoot.velocity); if (leftFoot.velocity == Vector3.zero || rightFoot.velocity == Vector3.zero) { Debug.Log("Step UP!"); hips.AddForce(Vector3.up * footStepUpwardForceStrength); } } }
/// <summary> /// Generates billboard corners. /// </summary> /// <remarks>Billboard param only required for type OrientedSelf</remarks> protected virtual void GenerateBillboardAxes( ref Vector3 x, ref Vector3 y, Billboard bb ) { // If we're using accurate facing, recalculate camera direction per BB if ( this.accurateFacing && ( this.billboardType == BillboardType.Point || this.billboardType == BillboardType.OrientedCommon || this.billboardType == BillboardType.OrientedSelf ) ) { // cam -> bb direction this.camDir = bb.Position - this.camPos; this.camDir.Normalize(); } switch ( this.billboardType ) { case BillboardType.Point: if ( this.accurateFacing ) { // Point billboards will have 'up' based on but not equal to cameras y = this.camQ * Vector3.UnitY; x = this.camDir.Cross( y ); x.Normalize(); y = x.Cross( this.camDir ); // both normalised already } else { // Get camera axes for X and Y (depth is irrelevant) x = this.camQ * Vector3.UnitX; y = this.camQ * Vector3.UnitY; } break; case BillboardType.OrientedCommon: // Y-axis is common direction // X-axis is cross with camera direction y = this.commonDirection; x = this.camDir.Cross( y ); x.Normalize(); break; case BillboardType.OrientedSelf: // Y-axis is direction // X-axis is cross with camera direction // Scale direction first y = bb.Direction; x = this.camDir.Cross( y ); x.Normalize(); break; case BillboardType.PerpendicularCommon: // X-axis is up-vector cross common direction // Y-axis is common direction cross X-axis x = this.commonUpVector.Cross( this.commonDirection ); y = this.commonDirection.Cross( x ); break; case BillboardType.PerpendicularSelf: // X-axis is up-vector cross own direction // Y-axis is own direction cross X-axis x = this.commonUpVector.Cross( bb.Direction ); x.Normalize(); y = bb.Direction.Cross( x ); // both should be normalised break; } #if NOT // Default behavior is that billboards are in local node space // so orientation of camera (in world space) must be reverse-transformed // into node space to generate the axes Quaternion invTransform = parentNode.DerivedOrientation.Inverse(); Quaternion camQ = Quaternion.Zero; switch (billboardType) { case BillboardType.Point: // Get camera world axes for X and Y (depth is irrelevant) camQ = camera.DerivedOrientation; // Convert into billboard local space camQ = invTransform * camQ; x = camQ * Vector3.UnitX; y = camQ * Vector3.UnitY; break; case BillboardType.OrientedCommon: // Y-axis is common direction // X-axis is cross with camera direction y = commonDirection; y.Normalize(); // Convert into billboard local space camQ = invTransform * camQ; x = camQ * camera.DerivedDirection.Cross(y); x.Normalize(); break; case BillboardType.OrientedSelf: // Y-axis is direction // X-axis is cross with camera direction y = billboard.Direction; // Convert into billboard local space camQ = invTransform * camQ; x = camQ * camera.DerivedDirection.Cross(y); x.Normalize(); break; case BillboardType.PerpendicularCommon: // X-axis is common direction cross common up vector // Y-axis is coplanar with common direction and common up vector x = commonDirection.Cross(commonUpVector); x.Normalize(); y = x.Cross(commonDirection); y.Normalize(); break; case BillboardType.PerpendicularSelf: // X-axis is direction cross common up vector // Y-axis is coplanar with direction and common up vector x = billboard.Direction.Cross(commonUpVector); x.Normalize(); y = x.Cross(billboard.Direction); y.Normalize(); break; } #endif }
public void Calculate_cross_product() { var firstOperand = new Vector3(1, 5, 6); var secondOperand = new Vector3(4, 9, 1); var actual = firstOperand.Cross(secondOperand); Assert.AreEqual(actual.X, -49); Assert.AreEqual(actual.Y, 23); Assert.AreEqual(actual.Z, -11); }
private static bool Orthogonal( Vector3 v1, Vector3 v2 ) { return v1.Cross( v2 ).Length < geometryEpsilon; }
public virtual bool HitTest(RenderContext context, Matrix modelMatrix, ref Ray rayWS, ref List <HitTestResult> hits, object originalSource) { if (Positions == null || Positions.Count == 0 || Indices == null || Indices.Count == 0) { return(false); } bool isHit = false; if (Octree != null) { isHit = Octree.HitTest(context, originalSource, this, modelMatrix, rayWS, ref hits); } else { var result = new HitTestResult { Distance = double.MaxValue }; var modelInvert = modelMatrix.Inverted(); if (modelInvert == Matrix.Zero)//Check if model matrix can be inverted. { return(false); } //transform ray into model coordinates var rayModel = new Ray(Vector3.TransformCoordinate(rayWS.Position, modelInvert), Vector3.TransformNormal(rayWS.Direction, modelInvert)); var b = this.Bound; //Do hit test in local space if (rayModel.Intersects(ref b)) { int index = 0; foreach (var t in Triangles) { var v0 = t.P0; var v1 = t.P1; var v2 = t.P2; if (Collision.RayIntersectsTriangle(ref rayModel, ref v0, ref v1, ref v2, out float d)) { if (d > 0 && d < result.Distance) // If d is NaN, the condition is false. { result.IsValid = true; result.ModelHit = originalSource; // transform hit-info to world space now: var pointWorld = Vector3.TransformCoordinate(rayModel.Position + (rayModel.Direction * d), modelMatrix); result.PointHit = pointWorld; result.Distance = (rayWS.Position - pointWorld).Length(); var p0 = Vector3.TransformCoordinate(v0, modelMatrix); var p1 = Vector3.TransformCoordinate(v1, modelMatrix); var p2 = Vector3.TransformCoordinate(v2, modelMatrix); var n = Vector3.Cross(p1 - p0, p2 - p0); n.Normalize(); // transform hit-info to world space now: result.NormalAtHit = n;// Vector3.TransformNormal(n, m).ToVector3D(); result.TriangleIndices = new System.Tuple <int, int, int>(Indices[index], Indices[index + 1], Indices[index + 2]); result.Tag = index / 3; result.Geometry = this; isHit = true; } } index += 3; } } if (isHit) { hits.Add(result); } } return(isHit); }
Vector3 right(Vector3 v1, Vector3 v2) { Vector3 first = (v2 - v1).normalized; return(roadWidth * Vector3.Cross(Vector3.down, first)); }
public float AngleSigned(Vector3 v1, Vector3 v2, Vector3 n)//return the angle between two vectors { return(Mathf.Atan2( Vector3.Dot(n, Vector3.Cross(v1, v2)), Vector3.Dot(v1, v2)) * Mathf.Rad2Deg); }
public void Align(Vector3 v1, Vector3 v2) { // If V1 and V2 are not parallel, the axis of rotation is the unit-length // vector U = Cross(V1,V2)/Length(Cross(V1,V2)). The angle of rotation, // A, is the angle between V1 and V2. The quaternion for the rotation is // q = cos(A/2) + sin(A/2)*(ux*i+uy*j+uz*k) where U = (ux,uy,uz). // // (1) Rather than extract A = acos(Dot(V1,V2)), multiply by 1/2, then // compute sin(A/2) and cos(A/2), we reduce the computational costs by // computing the bisector B = (V1+V2)/Length(V1+V2), so cos(A/2) = // Dot(V1,B). // // (2) The rotation axis is U = Cross(V1,B)/Length(Cross(V1,B)), but // Length(Cross(V1,B)) = Length(V1)*Length(B)*sin(A/2) = sin(A/2), in // which case sin(A/2)*(ux*i+uy*j+uz*k) = (cx*i+cy*j+cz*k) where // C = Cross(V1,B). // // If V1 = V2, then B = V1, cos(A/2) = 1, and U = (0,0,0). If V1 = -V2, // then B = 0. This can happen even if V1 is approximately -V2 using // floating point arithmetic, since Vector3::Normalize checks for // closeness to zero and returns the zero vector accordingly. The test // for exactly zero is usually not recommend for floating point // arithmetic, but the implementation of Vector3::Normalize guarantees // the comparison is robust. In this case, the A = pi and any axis // perpendicular to V1 may be used as the rotation axis. var bisector = v1.Add(v2); bisector.Normalise(); var cosHalfAngle = v1.Dot(bisector); Vector3 cross; tuple[0] = cosHalfAngle; if (cosHalfAngle != 0) { cross = v1.Cross(bisector); tuple[1] = cross.tuple[0]; tuple[2] = cross.tuple[1]; tuple[3] = cross.tuple[2]; } else { double invLength; if (System.Math.Abs(v1.tuple[0]) >= System.Math.Abs(v1.tuple[1])) { // V1.x or V1.z is the largest magnitude component invLength = 1 / System.Math.Sqrt(v1.tuple[0] * v1.tuple[0] + v1.tuple[2] * v1.tuple[2]); tuple[1] = - v1.tuple[2] * invLength; tuple[2] = 0; tuple[3] = + v1.tuple[0] * invLength; } else { // V1.y or V1.z is the largest magnitude component invLength = 1 / System.Math.Sqrt(v1.tuple[1] * v1.tuple[1] + v1.tuple[2] * v1.tuple[2]); tuple[1] = 0; tuple[2] = + v1.tuple[2] * invLength; tuple[3] = - v1.tuple[1] * invLength; } } }