public Camera(float aspect, int tempWidth, int tempHeight) { viewWidth = tempWidth; viewHeight = tempHeight; aspectRatio = aspect; m_cameraPos = new float3(0, 0, -3); m_cameraLookat = new float3(0, 0, 0); m_cameraUp = new float3(0, 1, 0); }
public Box(float3 min, float3 max) { m_min = min.Min(max); m_max = min.Max(max); }
public float3x3(float3 x, float3 y, float3 z) { m00 = x.x; m01 = x.y; m02 = x.z; m10 = y.x; m11 = y.y; m12 = y.z; m20 = z.x; m21 = z.y; m22 = z.z; }
// math functions public float Dot(float3 v) { return (x * v.x) + (y * v.y) + (z * v.z); }
public float3 Max(float3 v) { float3 ret = new float3(); ret.x = x > v.x ? x : v.x; ret.y = y > v.y ? y : v.y; ret.z = z > v.z ? z : v.z; return ret; }
public static float3 Lerp(float3 a, float3 b, float alpha) { return (a * (1.0f - alpha)) + (b * alpha); }
public float3 Cross(float3 v) { float3 ret = new float3(); ret.x = (y * v.z) - (z * v.y); ret.y = -((x * v.z) - (v.x * z)); ret.z = (x * v.y) - (v.x * y); return ret; }
public float4x4 OrthogonalBasis(float3 zaxis) { // from PBRT p54 float3 basisU; if( System.Math.Abs(zaxis.x) > System.Math.Abs(zaxis.y) ) { float invLen = 1.0f / (float)System.Math.Sqrt((zaxis.x*zaxis.x) + (zaxis.z*zaxis.z)); basisU = new float3(-zaxis.z * invLen, 0.0f, zaxis.x * invLen); } else { float invLen = 1.0f / (float)System.Math.Sqrt((zaxis.y*zaxis.y) + (zaxis.z*zaxis.z)); basisU = new float3(0.0f, zaxis.z * invLen, -zaxis.y * invLen); } float3 basisV = zaxis.Cross(basisU); float4x4 ret = Identity(); ret.m[0,0] = basisU.x; ret.m[0,1] = basisU.y; ret.m[0,2] = basisU.z; ret.m[1,0] = basisV.x; ret.m[1,1] = basisV.y; ret.m[1,2] = basisV.z; ret.m[2,0] = zaxis.x; ret.m[2,1] = zaxis.y; ret.m[2,2] = zaxis.z; return ret; }
public float4x4 OrthogonalBasis(float3 zaxis, float3 yaxis) { float4x4 ret = Identity(); return ret; }
public void SetUndefined() { m_min = new float3(float.MaxValue, float.MaxValue, float.MaxValue); m_max = new float3(float.MinValue, float.MinValue, float.MinValue); }
public float4x4(float3 x, float3 y, float3 z, float3 p) { m = new float[4,4]; m[0,0] = x.x; m[0,1] = x.y; m[0,2] = x.z; m[0,3] = 0.0f; m[1,0] = y.x; m[1,1] = y.y; m[1,2] = y.z; m[1,3] = 0.0f; m[2,0] = z.x; m[2,1] = z.y; m[2,2] = z.z; m[2,3] = 0.0f; m[3,0] = p.x; m[3,1] = p.y; m[3,2] = p.z; m[3,3] = 1.0f; }
public void MergePoint(float3 point1) { m_min = m_min.Min(point1); m_max = m_max.Max(point1); }
public void Intersection(Box box) { if (!Intersects(box)) { SetUndefined(); return; } m_min = m_min.Max(box.m_min); m_max = m_max.Min(box.m_max); }
public bool Contains(float3 point) { if (!IsDefined()) return false; if (m_min.x > point.x) return false; if (m_min.y > point.y) return false; if (m_min.z > point.z) return false; if (m_max.x < point.x) return false; if (m_max.y < point.y) return false; if (m_max.z < point.z) return false; return true; }
public static bool IntersectSphereAndLine(float3 pos, float radius, float3 posA, float3 posB, out float distance) { // Use dot product along line to find closest point on line float dot = (posB - posA).Normalize().Dot(pos - posA); float3 pointOnLine = (posB - posA) * dot; // Clamp that point to line end points if outside if ((dot - radius) < 0) pointOnLine = posA; if ((dot + radius) > (posB-posA).Length()) pointOnLine = posB; // Distance formula from that point to sphere center, compare with radius. distance = pointOnLine.Distance(pos); if (distance > radius) return false; return true; }
public float4x4 Rotate(float3 axis, float radians) { return Rotate(axis.x, axis.y, axis.z, radians); }
public static bool IntersectSphereAndTriangle(float3 pos, float radius, float3 posA, float3 posB, float3 posC, out float distance, out float3 normal) { distance = 0; normal = (posB - posA).Cross(posC - posA);// CrossProduct(posA, posB, posC); if (normal.Length() == 0.0f) throw new Exception("degenerate poly"); // project sphere center onto triangle, if the projection is inside the triangle, figure out // distance and return float3 edgeNormal1 = (posB - posA).Cross(normal); float3 edgeNormal2 = (posC - posB).Cross(normal); float3 edgeNormal3 = (posA - posC).Cross(normal); if ((edgeNormal1.Dot(pos - posA) <= 0) && (edgeNormal2.Dot(pos - posB) <= 0) && (edgeNormal3.Dot(pos - posC) <= 0)) { float lengthFromPlane = normal.Normalize().Dot(pos - posA); if (lengthFromPlane > radius) { return false; } else { distance = System.Math.Abs(lengthFromPlane); return true; } } // Intersect with all edges of the triangle. bool intersected; intersected = IntersectSphereAndLine(pos, radius, posA, posB, out distance); if (intersected) return true; intersected = IntersectSphereAndLine(pos, radius, posB, posC, out distance); if (intersected) return true; intersected = IntersectSphereAndLine(pos, radius, posC, posA, out distance); if (intersected) return true; return false; }
public float4x4 Scale(float3 v) { return Scale(v.x, v.y, v.z); }
public float3 Clamp(float3 min, float3 max) { return this.Max(min).Min(max); }
public float4x4 Translate(float3 v) { return Translate(v.x, v.y, v.z); }
public float Distance(float3 v) { float3 delta = v - this; float len = delta.Dot(delta); return (float)System.Math.Sqrt((double)len); }
public float3(float3 v) { x = v.x; y = v.y; z = v.z; }
public float3 Lerp(float3 v, float alpha) { return v * alpha + this * (1.0f - alpha); }
public float this[int index] { get { return ToArray()[index]; } set { float[] f = ToArray(); f[index] = value; this = new float3(f); } }
public float3 Min(float3 v) { float3 ret = new float3(); ret.x = x < v.x ? x : v.x; ret.y = y < v.y ? y : v.y; ret.z = z < v.z ? z : v.z; return ret; }
public static float dot(float3 a, float3 b) { return a.Dot(b); }
private void Dolly(float amount) { float3 lookAtDelta = m_cameraPos - m_cameraLookat; // If we try to dolly too far at once, we'll go through the origin and back out the other side. So clamp it. if (amount > 360) amount = 360; if (amount < -360) amount = -360; // If our frail floating point numbers get too small, force a dolly outwards. Too small causes degenerate case. :( if (lookAtDelta.Length() < 0.0001f) amount = -Math.Abs(amount); m_cameraPos -= lookAtDelta * amount * 0.0015f; }
public static bool IntersectLineAndTriangle(float3 posVec, float3 velVec, float3 posA, float3 posB, float3 posC, out float3 intersection, out float t, bool doubleSided) { float3 normal; //normal = (posC - posA).Cross(posB - posA);// CrossProduct(posA, posB, posC); normal = (posB - posA).Cross(posC - posA);// CrossProduct(posA, posB, posC); if (normal.Length() == 0.0f) throw new Exception("degenerate poly"); // degenerate cases (line parallel to plane) result in no collision. float3 pointOnPoly; pointOnPoly = posB; float3 startSide, endSide; // get the start position of the line we're projecting on // then get the start position of the line relative to the plane startSide = pointOnPoly - posVec; // next get the end position of the line we're projecting on // and make it relative to the start position of the line //endSide = velVec - posVec; // absolute velVec position. //if (endSide == new float3(0.0f, 0.0f, 0.0f)) throw new Exception("parallel. not handled yet."); // parallel movement endSide=velVec; // relative velVec position. // Do dot products for intersection float startDot, endDot; // compute the dot product of the normal of the plane and the start of the line relative to the plane startDot = normal.Dot(startSide); // ASSERT(startDot!=0.0); // and then compute the dot product of the plane normal, and the length of the vector endDot = normal.Dot(endSide); // ASSERT(endDot!=0.0); // if both are negative then flip both, to intersect 'double sided' if (doubleSided) { if ((endDot > 0.0f) && (startDot > 0.0f)) { endDot = -endDot; startDot = -startDot; } } t = 1.0f; intersection = posVec + velVec; if ((endDot < 0.0f) && (startDot < 0.0f)) { // line is now infinite. if (endDot <= startDot) { // Guess there was a line with plane intersection. t = startDot / endDot; // get parametric t variable of where the intersection was. // if (*t<0.0) *t=0.0; if ((t < 0.0f) || (t > 1.0f)) throw new Exception("oops"); intersection = (endSide * t) + posVec; float x0, y0, x1, y1, x2, y2, xc, yc; // 2-d polygon coordinates. // Project polygon into 2-d to simplify the next step. if ((System.Math.Abs(normal.x) >= System.Math.Abs(normal.y)) && (System.Math.Abs(normal.x) >= System.Math.Abs(normal.z))) { x0 = posA.z; y0 = posA.y; x1 = posB.z; y1 = posB.y; x2 = posC.z; y2 = posC.y; xc = intersection.z; yc = intersection.y; } else { if ((System.Math.Abs(normal.y) >= System.Math.Abs(normal.x)) && (System.Math.Abs(normal.y) >= System.Math.Abs(normal.z))) { x0 = posA.x; y0 = posA.z; x1 = posB.x; y1 = posB.z; x2 = posC.x; y2 = posC.z; xc = intersection.x; yc = intersection.z; } else { // z is greastest x0 = posA.x; y0 = posA.y; x1 = posB.x; y1 = posB.y; x2 = posC.x; y2 = posC.y; xc = intersection.x; yc = intersection.y; } } // Do determinants to find out if point of intersection is inside triangle. float alpha, beta, u0, v0, u1, v1, u2, v2, quickDot; u0 = xc - x1; v0 = yc - y1; u1 = x2 - x1; v1 = y2 - y1; u2 = x0 - x1; v2 = y0 - y1; quickDot = u1 * v2 - u2 * v1; if (quickDot != 0.0f) { alpha = (u0 * v2 - u2 * v0) / quickDot; beta = (u1 * v0 - u0 * v1) / quickDot; if ((alpha >= 0.0f) && (beta >= 0.0f) && (alpha + beta <= 1.0f)) { // collision happened. Save values or do whatever must be done. return true; } } } } return false; }
public void UpdateMouseControls() { if (leftButton || rightButton) { float2 delta = new float2((mousePos - dragStart) * 2); delta.x *= aspectRatio; delta /= viewWidth; if (leftButton && rightButton) { Dolly(delta.x * 1000); } else { if (leftButton) { // rotation camera float sensitivity = 1.5f; float3x3 roty = float3x3.RotateY(delta.x * sensitivity); float3 lookAtDelta = m_cameraPos - m_cameraLookat; lookAtDelta = roty.Mul(lookAtDelta); float3 rightVector = lookAtDelta.Cross(m_cameraUp).Normalize(); float3x3 upRot = float3x3.AxisAngle(rightVector, delta.y * sensitivity); lookAtDelta = upRot.Mul(lookAtDelta); m_cameraPos = lookAtDelta + m_cameraLookat; float3 newLookAtDelta = m_cameraPos - m_cameraLookat; float3 newRightVector = newLookAtDelta.Cross(m_cameraUp).Normalize(); if (newRightVector.Dot(rightVector) < 0) m_cameraUp.y = -m_cameraUp.y; } else { // move camera float3 lookAtDelta = m_cameraPos - m_cameraLookat; float3 rightVector = lookAtDelta.Cross(m_cameraUp).Normalize(); float3 upVector = rightVector.Cross(lookAtDelta).Normalize(); float moveScale = 0.5f * lookAtDelta.Length(); m_cameraPos -= rightVector * delta.x * moveScale; m_cameraLookat -= rightVector * delta.x * moveScale; m_cameraPos += upVector * delta.y * moveScale; m_cameraLookat += upVector * delta.y * moveScale; } } } SetupCamera(); }
public static Quaternion FromAxisAngle( float3 axis, float theta ) { float sumOfSquares = axis.x * axis.x + axis.y * axis.y + axis.z * axis.z; if (sumOfSquares <= 1.0e-5F) { return new Quaternion( 0, 0, 0, 1 ); } else { theta *= 0.5f; float commonFactor = (float)System.Math.Sin(theta); if( sumOfSquares != 1.0 ) commonFactor /= (float)System.Math.Sqrt(sumOfSquares); return new Quaternion( commonFactor * axis.x, commonFactor * axis.y, commonFactor * axis.z, (float)System.Math.Cos(theta) ); } }