/// <summary> /// Copy constructor. /// </summary> /// <param name="?"></param> public Vector(Vector vectSource) { if (vectSource == null) throw new Exception("Error in Vector.Vector() - source vector cannot be null."); Resize(vectSource.arrVector.Length, false); for (int iIndex = 0; iIndex < vectSource.arrVector.Length; iIndex++) { arrVector[iIndex] = vectSource.arrVector[iIndex]; } }
private Color VectorToColor(Vector vectColor) { vectColor = vectColor.Limit(0, 1.0); Color clNewColor = Color.FromArgb((int)(vectColor[0] * 255), (int)(vectColor[1] * 255.0), (int)(vectColor[2] * 255.0)); return clNewColor; }
private Vector ColorToVector(Color clColor){ Vector vectColor = new Vector(3, true); vectColor[0] = clColor.R / 255.0; // red component vectColor[1] = clColor.G / 255.0; // green component vectColor[2] = clColor.B / 255.0; // blue component return vectColor; }
public void SetupVectA() { vectA = new Vector(3); vectA[0] = 2; vectA[1] = -1; vectA[2] = 1; }
public PointLightSource(double dXPos, double dYPos, double dZPos) { vectPosition = new Vector(dXPos, dYPos, dZPos); }
public override double IntersectionTest(Vector vectRay, Vector vectOrigin) { throw new Exception("The method or operation is not implemented."); }
public override double IntersectionTest(Vector vectRayStart, Vector vectRayEnd) { Vector vectRayDirection = (vectRayEnd - vectRayStart).Normalize(); double dA = vectRayDirection.DotProduct(vectRayDirection); Vector vectSphereToRayOrigin = vectRayStart - vectPosition; double dB = 2 * vectRayDirection.DotProduct(vectSphereToRayOrigin); double dC = (vectSphereToRayOrigin).DotProduct(vectSphereToRayOrigin) - (dRadius * dRadius); double dDiscriminant = (dB * dB) - (4 * dA * dC); double dt = 0; double dt1, dt2; if (dDiscriminant >= 0) // has a solution { dt1 = (-dB - Math.Sqrt(dDiscriminant)) / (2.0 * dA); dt2 = (-dB + Math.Sqrt(dDiscriminant)) / (2.0 * dA); if (dt1 < dt2) dt = dt1; else dt = dt2; } return dt; }
/// <summary> /// An interstion test performs an analysis along a ray to determine if /// the ray passes through a 3d object in a scene. The value returned /// reflect the point along that ray where the insesction begins. /// /// If zero is returned, then no intersection has occured. /// /// To get the actual 3D position where the intersection occured, use the /// following formula (where t is a possible value returned): /// /// p(t) = o + t(s - o) /// /// Where o is the origin position (vectOrigin), t is the value returned /// by this method, and s is the direction vector (vectRay). /// </summary> public abstract double IntersectionTest(Vector vectRayStart, Vector vectRayEnd);
/// <summary> /// Creates a new vector that is the unit vector for /// for this vector. /// </summary> public Vector Normalize() { if (arrVector == null) return new Vector(0); Vector vectNormalized = new Vector(arrVector.Length, true); double dUnitLength = Length; if (arrVector != null && dUnitLength > 0) { for (int iIndex = 0; iIndex < arrVector.Length; iIndex++) { vectNormalized[iIndex] = arrVector[iIndex] / dUnitLength; } } return vectNormalized; }
/// <summary> /// Returns the dot product of this and the second provided vector, /// </summary> /// <param name="vect"></param> /// <returns></returns> public double DotProduct(Vector vect) { if (vect == null) return 0; if (vect.arrVector == null || arrVector == null) throw new Exception ("Error in Vector.DotProduct(). The vector cannot be a null vector."); if (vect.Size != Size) throw new Exception ("Error in Vector.DotProduct(). Both vectors cannot be of the same size."); double dResult = 0; for (int iIndex = 0; iIndex < arrVector.Length; iIndex++) { dResult += vect.arrVector[iIndex] * arrVector[iIndex]; } return dResult; }
/// <summary> /// Calculates the angle betweeen two vectors. Angle returned is in degrees. /// </summary> public double Angle(Vector vect) { double dVal = DotProduct(vect) / (Length * vect.Length); return Math.Acos(dVal) * (180.0 / Math.PI); }
public static Vector operator* (Vector vect1, Vector vect2) { if (vect1 == null || vect2 == null) throw new NullReferenceException(); if (vect1.arrVector == null || vect2.arrVector == null) throw new Exception("Multiplying by null vector is not permitted."); if (vect1.arrVector.Length != vect2.arrVector.Length) throw new Exception("Multiplying two vectors together by different lengths is not permitted."); Vector vectResult = new Vector(vect1.arrVector.Length, true); for (int iIndex = 0; iIndex < vect1.arrVector.Length; iIndex++) { vectResult.arrVector[iIndex] = vect1.arrVector[iIndex] * vect2.arrVector[iIndex]; } return vectResult; }
public static Vector operator* (Vector vect, double dVal) { if (vect == null) throw new NullReferenceException(); if (vect.arrVector == null) throw new Exception("Scaling a null vector is not permitted."); Vector vectResult = new Vector(vect.arrVector.Length, true); for (int iIndex = 0; iIndex < vect.arrVector.Length; iIndex++) { vectResult.arrVector[iIndex] = dVal * vect.arrVector[iIndex]; } return vectResult; }
public static Vector operator- (Vector vect1, Vector vect2) { if (vect1 == null || vect2 == null) throw new NullReferenceException(); if (vect1.arrVector == null || vect2.arrVector == null) throw new Exception("Subtraction of null vectors is not permitted."); if (vect1.arrVector.Length != vect2.arrVector.Length) throw new Exception("Cannot subtract - vectors are not of the same size."); Vector vectResult = new Vector(vect1.arrVector.Length, true); for (int iIndex = 0; iIndex < vect1.arrVector.Length; iIndex++) { vectResult.arrVector[iIndex] = vect1.arrVector[iIndex] - vect2.arrVector[iIndex]; } return vectResult; }
public void SetupVectB() { vectB = new Vector(3); vectB[0] = 1; vectB[1] = 1; vectB[2] = 2; }
public Camera(double dXPos, double dYPos, double dZPos, double dLookAtX, double dLookAtY, double dLookAtZ, double dUpX, double dUpY, double dUpZ) { vectPosition = new Vector(dXPos, dYPos, dZPos); vectLookAt = new Vector(dLookAtX, dLookAtY, dLookAtZ); vectUp = new Vector(dUpX, dUpY, dUpZ); }
public Object3D(double dXPos, double dYPos, double dZPos) { vectPosition = new Vector(dXPos, dYPos, dZPos); }
/// <summary> /// Adjusts the values of a vector so that they are within /// the limits imposed by Min and Max. /// </summary> /// <param name="dMin"></param> /// <param name="dMax"></param> /// <returns></returns> public Vector Limit(double dMin, double dMax) { if (arrVector == null) return new Vector(0); if (dMin > dMax) { double dTemp = dMin; dMin = dMax; dMax = dTemp; } Vector vectLimited = new Vector(arrVector.Length, true); for (int iIndex = 0; iIndex < vectLimited.Size; iIndex++) { if (arrVector[iIndex] < dMin) vectLimited[iIndex] = dMin; else if (arrVector[iIndex] > dMax) vectLimited[iIndex] = dMax; else vectLimited[iIndex] = arrVector[iIndex]; } return vectLimited; }
public abstract Vector GetSurfaceNormal(Vector vectSurfacePosition);
/// <summary> /// Copy constructor with a vector. /// </summary> public Matrix (Vector vect) { Assign(vect); }
public override Vector GetSurfaceNormal(Vector vectSurfacePosition) { return (vectSurfacePosition - vectPosition).Normalize(); }
/// <summary> /// Makes the matrix an exact duplicate of the provided vector. /// </summary> public void Assign(Vector vect) { int iColumns = vect.Size; arrMatrix = Create2DArray(1, iColumns); if (arrMatrix == null) return; for (int iCol = 0; iCol < iColumns; iCol++) { arrMatrix[0, iCol] = vect[iCol]; } }
public override Vector GetSurfaceNormal(Vector vectSurfacePosition) { Vector vectNormal = (vectSurfacePosition - vectPosition).Normalize(); // *(1.0 / dSize); return vectNormal; }
/// <summary> /// Multiplies a vector by the matrix in order to produce a new vector. /// An exception is thrown if the vector has a size that is not equal /// to then number of rows in the matrix, or if the matrix is null or /// vector is null. Equivalent to VECT * MAT = VECT /// </summary> public Vector Multiply(Vector vect) { if (vect == null) throw new NullReferenceException("Error in Matrix.Multiply." + "Provided vector object is null."); if (arrMatrix == null) throw new Exception("Error in Matrix.Multiply. " + "This matrix is a null matrix."); if (vect.IsNull) throw new Exception("Error in Matrix.Multiply. " + "Provided vector is a null vector."); int iRows = Rows; int iColumns = Columns; if (iRows != vect.Size) throw new Exception("Error in Matrix.Multiply. " + "The number vector is not the same size as the number " + "of rows in the matrix."); // convert the vector to a matrix Matrix matResult = new Matrix(vect); matResult = matResult.Multiply(this); // create a new matrix that is of the same # or rows as the result Vector vectResult = new Vector(iColumns); for (int iIndex = 0; iIndex < iColumns; iIndex++) { vectResult[iIndex] = matResult[0, iIndex]; } return vectResult; }
private Vector TraceRay(Vector vectRayStart, Vector vectRayEnd, int iRayCount) { // establish a vector of base intenisites (current "black"). Vector vectIntensity = new Vector(3); Vector vectSpecular = new Vector(3); // make sure we don't recurse any more than we have to if (iRayCount > iMaxRecursion) return vectIntensity; // first, find the object that intersects the ray at the start position Object3D obj3dClosest = null; double dtClosest = 0; for (int iIndex = 0; iIndex < arrObjects.Count; iIndex++) { Object3D obj3dCurrent = (Object3D)arrObjects[iIndex]; if (obj3dCurrent == null) continue; // convert the object to eye coordinates double dtCurrent = obj3dCurrent.IntersectionTest(vectRayStart, vectRayEnd); // check for any intersection if (dtCurrent <= 0) continue; // intersection - ray has hit an object if (obj3dClosest == null || dtCurrent < dtClosest) { obj3dClosest = obj3dCurrent; dtClosest = dtCurrent; } } // no object intersect the ray, so return black, or 0 intensity if (obj3dClosest == null) return vectIntensity; // shadow ray flag bool bIsShadowRay = false; // establish a base intensity of the object vectIntensity = vectAmbientLightIntensity * vectAmbientLightColor * obj3dClosest.AmbientColor; // now, go through all point light sources, and see if it // influences the color of the light // get 3d position where the ray touched the object Vector vectRay = (vectRayEnd - vectRayStart).Normalize(); Vector vectSurfacePoint = vectRayStart + dtClosest * vectRay; // get the normal of the surface hit Vector vectSurfaceNormal = obj3dClosest.GetSurfaceNormal(vectSurfacePoint); // tiny adjustment vectSurfacePoint += (vectSurfaceNormal * 0.01); for (int iIndex = 0; iIndex < arrPointLightSources.Count; iIndex++) { // get the point light source in the scene PointLightSource plsLight = (PointLightSource)arrPointLightSources[iIndex]; if (plsLight == null) continue; bIsShadowRay = false; // convert the light source to UVW coodinates //Vector vectLightRay = plsLight.Position - vectSurfacePoint; // test to see how far away the light intersects the vector // dt = obj3dClosest.IntersectionTest(plsLight.Position, vectSurfacePoint); // test to see if the ray is in the shadow of another object wrt // the light source - assuming that the light ray to the surface of // of the object is 1.0, then any objects between the light source // and the current object will have a value between 0 and 1 for (int iIndex2 = 0; iIndex2 < arrObjects.Count; iIndex2++) { Object3D obj3dCurrent = (Object3D)arrObjects[iIndex2]; if (obj3dCurrent == null || obj3dClosest == obj3dCurrent) continue; dtClosest = obj3dCurrent.IntersectionTest(vectSurfacePoint, plsLight.Position); // yes, there is another object in the way of this object, so the // ray cast by the light source is actually a shadow ray for this object if (dtClosest > 0) { bIsShadowRay = true; break; } } // if the ray is a shadow ray, then the light from the light source does not contribute // to the light in the ray, so just continue on to the next light source if (bIsShadowRay) continue; // ok, so the light source contributes to the light shown on the object Vector vectLightVector = (plsLight.Position - vectSurfacePoint).Normalize(); //Vector vectLightVector = new Vector(0, 1, 0); // calculate diffuse component of the light source Vector vectDiffuse = (plsLight.Diffuse * obj3dClosest.DiffuseColor * vectSurfaceNormal.DotProduct(vectLightVector)).Limit(0,1); vectIntensity += vectDiffuse; // get the inverse of the viewing ray // calculate specular component of the light source // get the "Halfway" vector Vector vectH = (vectLightVector + vectRay * -1).Normalize(); vectSpecular = (plsLight.Specular * obj3dClosest.SpecularColor * Math.Pow(vectH.DotProduct(vectSurfaceNormal), obj3dClosest.SpecularPow)).Limit(0, 1); vectIntensity += vectSpecular; } Vector vectRecursiveRay = vectRay - (2 * vectRay.DotProduct(vectSurfaceNormal) * vectSurfaceNormal); Vector vectReflectiveIntensity = (TraceRay(vectSurfacePoint, vectRecursiveRay + vectSurfacePoint, ++iRayCount)).Limit(0, 1); vectIntensity += obj3dClosest.SpecularColor * vectReflectiveIntensity; // add the final and reflective colors together return vectIntensity; // +vectReflectiveIntensity; }
public static Vector CrossProduct(Vector vectA, Vector vectB) { if (vectA == null || vectB == null) throw new NullReferenceException(); if (vectA.Size == 0 || vectB.Size == 0) throw new Exception("Error in MatrixMath.CrossProduct. Neither vector can be a null vector."); if (vectA.Size != 3 || vectB.Size != 3) throw new Exception("Error in MatrixMath.CrossProduct. Both vectors must be of size 3."); return new Vector( vectA[1] * vectB[2] - vectA[2] * vectB[1], vectA[2] * vectB[0] - vectA[0] * vectB[2], vectA[0] * vectB[1] - vectA[1] * vectB[0]); }