public Tube( IRenderer renderer ) { ReferenceVertices = new GLVector3d[ 4 ]; ReferenceVertices[0] = new GLVector3d( 0.5, -0.5, 0 ); ReferenceVertices[1] = new GLVector3d( 0.5, 0.5, 0 ); ReferenceVertices[2] = new GLVector3d( -0.5, 0.5, 0 ); ReferenceVertices[3] = new GLVector3d( -0.5, -0.5, 0 ); iFirstOuterFace = 0; iLastOuterFace = 3; iNumberFaces = 4; bShowCut = false; bShowHollow = false; iCutStart = 0; iCutEnd = MaxCut; this.renderer = renderer; SendRendererCallbacksToCrossSections(); rotationalextrusionpath.UpdatePath(); BuildFaces(); }
//!Get the matrix vector dot product with w = 1, use for transforming non 4D vectors public static GLVector3d operator*(GLMatrix4d mat, GLVector3d vec) { GLVector3d ret = new GLVector3d(); for (byte j = 0; j < 3; ++j) { for (byte i = 0; i < 3; ++i) { ret.val[j] += vec.val[i] * mat.m[j + i * 4]; //scale and rotate disregarding w scaling } } for (byte i = 0; i < 3; ++i) { ret.val[i] += mat.m[i + 3 * 4]; //translate } //do w scaling double w = mat.m[15]; for (byte i = 0; i < 3; ++i) { w += vec.val[i] * mat.m[3 + i * 4]; } double resip = 1 / w; for (byte i = 0; i < 3; ++i) { ret.val[i] *= resip; } return(ret); }
//!Apply an OpenGL translate matrix to this public GLMatrix4d applyTranslate(GLVector3d trans) { //improved version m[12] += m[0] * trans.x + m[4] * trans.y + m[8] * trans.z; m[13] += m[1] * trans.x + m[5] * trans.y + m[9] * trans.z; m[14] += m[2] * trans.x + m[6] * trans.y + m[10] * trans.z; return(this); }
//!Apply an OpenGL scale matrix to this public GLMatrix4d applyScale(GLVector3d scale) { //improved version m[0] *= scale.x; m[1] *= scale.x; m[2] *= scale.x; m[3] *= scale.x; m[4] *= scale.y; m[5] *= scale.y; m[6] *= scale.y; m[7] *= scale.y; m[8] *= scale.z; m[9] *= scale.z; m[10] *= scale.z; m[11] *= scale.z; return(this); }
//!Apply the cross-product of this and a vector public GLVector3d cross(GLVector3d gv) { double[] temp = new double[] { x, y, z }; x = temp[1] * gv.z - temp[2] * gv.y; y = temp[2] * gv.x - temp[0] * gv.z; z = temp[0] * gv.y - temp[1] * gv.x; return(this); }
//!OpenGL View Matrix. public GLMatrix4d loadView(GLVector3d front, GLVector3d up, GLVector3d side) { m[0] = side.x; m[1] = up.x; m[2] = -front.x; m[3] = 0; m[4] = side.y; m[5] = up.y; m[6] = -front.y; m[7] = 0; m[8] = side.z; m[9] = up.z; m[10] = -front.z; m[11] = 0; m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1; return(this); }
protected virtual void RenderEndCapNoHollow( bool IsTop ) { GLVector3d rawcentre = new GLVector3d(); if( !IsTop ) { GLVector3d p0 = rotationalextrusionpath.GetTransformedVertex( new GLVector3d( 0, 0, 0 ), 0 ); Vector2 t0 = texturemapping.GetTextureCoordinate( new Vector2( 0.5, 0.5 ) ); for( int i = iFirstOuterFace; i <= iLastOuterFace; i++ ) { GLVector3d p1 = OuterFaces[i].GetTransformedVertex( rotationalextrusionpath, 0, 0 ); GLVector3d p2 = OuterFaces[i].GetTransformedVertex( rotationalextrusionpath, 0, 1 ); GLVector3d r1 = OuterFaces[i].GetRawVertex( 0 ); GLVector3d r2 = OuterFaces[i].GetRawVertex( 1 ); Vector2 t1 = texturemapping.GetTextureCoordinate( new Vector2( 1 - ( r1.x + 0.5 ), r1.y + 0.5 ) ); Vector2 t2 = texturemapping.GetTextureCoordinate( new Vector2( 1 - ( r2.x + 0.5 ), r2.y + 0.5 ) ); GLVector3d normal = CalculateNormal( p2,p1,p0 ); renderer.SetNormal( normal.x, normal.y, normal.z ); renderer.StartTriangle(); renderer.SetTextureCoord( t0.x, t0.y ); renderer.AddVertex( p0.x, p0.y, p0.z ); renderer.SetTextureCoord( t2.x, t2.y ); renderer.AddVertex( p2.x, p2.y, p2.z ); renderer.SetTextureCoord( t1.x, t1.y ); renderer.AddVertex( p1.x, p1.y, p1.z ); renderer.EndTriangle(); } } else { GLVector3d p0 = rotationalextrusionpath.GetTransformedVertex( new GLVector3d( 0, 0, 0 ), rotationalextrusionpath.NumberOfTransforms - 1 ); Vector2 t0 = texturemapping.GetTextureCoordinate( new Vector2( 0.5, 0.5 ) ); for( int i = iFirstOuterFace + 1; i < iLastOuterFace; i++ ) { GLVector3d p1 = OuterFaces[i].GetTransformedVertex( rotationalextrusionpath, rotationalextrusionpath.NumberOfTransforms - 1, 0 ); GLVector3d p2 = OuterFaces[i].GetTransformedVertex( rotationalextrusionpath, rotationalextrusionpath.NumberOfTransforms - 1, 1 ); GLVector3d r1 = OuterFaces[i].GetRawVertex( 0 ); GLVector3d r2 = OuterFaces[i].GetRawVertex( 1 ); Vector2 t1 = texturemapping.GetTextureCoordinate( new Vector2( r1.x + 0.5, r1.y + 0.5 ) ); Vector2 t2 = texturemapping.GetTextureCoordinate( new Vector2( r2.x + 0.5, r2.y + 0.5 ) ); GLVector3d normal = CalculateNormal( p2,p1,p0 ); renderer.SetNormal( normal.x, normal.y, normal.z ); renderer.StartTriangle(); renderer.SetTextureCoord( t0.x, t0.y ); renderer.AddVertex( p0.x, p0.y, p0.z ); renderer.SetTextureCoord( t1.x, t1.y ); renderer.AddVertex( p1.x, p1.y, p1.z ); renderer.SetTextureCoord( t2.x, t2.y ); renderer.AddVertex( p2.x, p2.y, p2.z ); renderer.EndTriangle(); } } }
//!Apply an OpenGL translate matrix to this public GLMatrix4d applyTranslate( GLVector3d trans) { //improved version m[12] += m[0]*trans.x + m[4]*trans.y + m[8]*trans.z; m[13] += m[1]*trans.x + m[5]*trans.y + m[9]*trans.z; m[14] += m[2]*trans.x + m[6]*trans.y + m[10]*trans.z; return this; }
//!Get the matrix vector dot product with w = 1, use for transforming non 4D vectors public static GLVector3d operator* ( GLMatrix4d mat, GLVector3d vec) { GLVector3d ret = new GLVector3d(); for(byte j = 0; j < 3; ++j) for(byte i = 0; i < 3; ++i) ret.val[j] += vec.val[i]*mat.m[j+i*4]; //scale and rotate disregarding w scaling for(byte i = 0; i < 3; ++i) ret.val[i] += mat.m[i+3*4]; //translate //do w scaling double w = mat.m[15]; for(byte i = 0; i < 3; ++i) w += vec.val[i]*mat.m[3+i*4]; double resip = 1/w; for(byte i = 0; i < 3; ++i) ret.val[i] *= resip; return ret; }
//!Get the projection of this and a vector public double projection( GLVector3d vin) { return dot(vin); }
//!Get the cross-product of this and a vector public GLVector3d getCross( GLVector3d gv) { return new GLVector3d(y*gv.z-z*gv.y,z*gv.x-x*gv.z,x*gv.y-y*gv.x); }
//!Apply the cross-product of this and a vector public GLVector3d cross( GLVector3d gv) { double[] temp = new double[]{ x, y, z }; x = temp[1] * gv.z - temp[2] * gv.y; y = temp[2] * gv.x - temp[0] * gv.z; z = temp[0] * gv.y - temp[1] * gv.x; return this; }
protected override void BuildFaces() { // cout << endl << endl << "PrimitiveCylinderImpl, BuildFaces() >>>" << endl; if( iCutStart == 0 && iCutEnd == MaxCut ) { bShowCut = false; } else { bShowCut = true; } if( iHollow == 0 ) { bShowHollow = false; } else { bShowHollow = true; } double fHollowRatio = (double)iHollow / 100; GLVector3d cutstartinnerface = null; GLVector3d cutendinnerface = null; GLVector3d cutstartouterface = GetCutIntersect( iCutStart, 0.5 ); GLVector3d cutendouterface = GetCutIntersect( iCutEnd, 0.5 ); if( bShowHollow ) { cutstartinnerface = GetCutIntersect( iCutStart, fHollowRatio * 0.5 ); cutendinnerface = GetCutIntersect( iCutEnd, fHollowRatio * 0.5 ); } if( bShowCut ) { BuildCutFaces( cutstartouterface, cutstartinnerface, cutendouterface, cutendinnerface ); } OuterFaces[0].RemoveAllPoints(); InnerFaces[0].RemoveAllPoints(); double fAngle = 0; double fStartAngle = (double)iCutStart / (double)MaxCut * 2 * Math.PI; double fEndAngle = (double)iCutEnd / (double)MaxCut * 2 * Math.PI; GLVector3d NextOuterPoint = new GLVector3d(); GLVector3d NextInnerPoint = new GLVector3d(); int iFacePoint = 0; for( iFacePoint = 0; iFacePoint <= iLevelOfDetail; iFacePoint++ ) { fAngle = fStartAngle + (double)iFacePoint / (double)iLevelOfDetail * ( fEndAngle - fStartAngle ); NextOuterPoint.x = 0.5 * Math.Cos( fAngle ); NextOuterPoint.y = 0.5 * Math.Sin( fAngle ); OuterFaces[0].AddPoint( NextOuterPoint.x, NextOuterPoint.y, NextOuterPoint.z ); } if( bShowHollow ) { for( iFacePoint = iLevelOfDetail; iFacePoint >= 0; iFacePoint-- ) { fAngle = fStartAngle + (double)iFacePoint / (double)iLevelOfDetail * ( fEndAngle - fStartAngle ); NextInnerPoint.x = 0.5 * Math.Cos( fAngle ) * (double)iHollow / 100.0; NextInnerPoint.y = 0.5 * Math.Sin( fAngle ) * (double)iHollow / 100.0; InnerFaces[0].AddPoint( NextInnerPoint.x, NextInnerPoint.y, NextInnerPoint.z ); } } OuterFaces[0].TextureMapping = texturemapping; InnerFaces[0].TextureMapping = texturemapping; AssignFaces(); }
protected void BuildCutFaces( GLVector3d cutstartouterface, GLVector3d cutstartinnerface, GLVector3d cutendouterface, GLVector3d cutendinnerface ) { CutFaces[0].RemoveAllPoints(); if( bShowHollow ) { CutFaces[0].AddPoint(cutstartinnerface ); } else { CutFaces[0].AddPoint( 0, 0, 0 ); } CutFaces[0].AddPoint(cutstartouterface ); CutFaces[0].TextureMapping = texturemapping; CutFaces[1].RemoveAllPoints(); CutFaces[1].AddPoint(cutendouterface ); if( bShowHollow ) { CutFaces[1].AddPoint(cutendinnerface ); } else { CutFaces[1].AddPoint( 0, 0, 0 ); } CutFaces[1].TextureMapping = texturemapping; }
// for quads protected GLVector3d CalculateNormal( GLVector3d p1,GLVector3d p2,GLVector3d p3,GLVector3d p4 ) { GLVector3d vectorac = p3 - p1; GLVector3d vectorbd = p4 - p2; return vectorac.getCross( vectorbd ).unit(); }
// useful for triangles protected GLVector3d CalculateNormal( GLVector3d p1,GLVector3d p2,GLVector3d p3 ) { GLVector3d vectorab = p2 - p1; GLVector3d vectorac = p3 - p1; return vectorab.getCross( vectorac ).unit(); }
public void AddPoint( double x, double y, double z ) { points[iNumPoints] = new GLVector3d( x, y, z ); iNumPoints++; }
public void AddPoint( GLVector3d point ) { points[iNumPoints] = new GLVector3d( point ); iNumPoints++; }
//! BAsically we check the quadrant (0 to 3), then intersect the radius with the face corresponding to that quadrant // The cut starts from the clockwise-end vertex of quadrant 0, and rotates anticlockwise; assuming x points right and y points up GLVector3d GetCutIntersect( int iCut, double fCubeHalfWidth ) { int iCutQuadrant = GetCutQuadrant( iCut ); double fCutRatio = (double)iCut / (double)MaxCut; GLVector3d lineend = null; GLVector3d linestart = ReferenceVertices[ iCutQuadrant] * fCubeHalfWidth / 0.5; if( iCutQuadrant < iNumberFaces - 1 ) { lineend = ReferenceVertices[ iCutQuadrant + 1 ] * fCubeHalfWidth / 0.5; } else { lineend = ReferenceVertices[ 0 ] * fCubeHalfWidth / 0.5; } double fAngle = GetAngleWithXAxis( fCutRatio ); // CutVectorPerp is perpendicular to the radius vector, I think GLVector3d CutVectorPerp = new GLVector3d( - Math.Sin( fAngle ), Math.Cos( fAngle ), 0 ); // Grabbed this from http://softsurfer.com/Archive/algorithm_0104/algorithm_0104B.htm GLVector3d IntersectPoint = linestart - ( lineend - linestart ) * CutVectorPerp.dot( linestart ) / CutVectorPerp.dot( lineend - linestart ); //Console.WriteLine( "GetCutIntersect iCut " + iCut.ToString() + " cubehalfwidth " + fCubeHalfWidth.ToString() + " linestart " + linestart.ToString() + // lineend.ToString() + " fAngle " + fAngle.ToString() + " CutVectorPerp " + CutVectorPerp.ToString() + " intersectpoint " + IntersectPoint.ToString() ); return IntersectPoint; }
public GLVector3d GetTransformedVertex( GLVector3d PointToTransform, int iTransformIndex ) { return transforms[ iTransformIndex ] * PointToTransform; }
// Handles the first face in the cut, starting from cutstart, and running anticlockwise to first reference vertex (assuming x points right, y points up) double PopulateSingleCutFacePositiveDirection( ref CrossSection face, GLVector3d CutPoint, int iQuadrant, double fHalfCubeWidth, bool bOuter ) { iQuadrant = NormalizeQuadrant( iQuadrant ); face.RemoveAllPoints(); GLVector3d StartPoint = new GLVector3d( CutPoint ); GLVector3d EndPoint = null; if( iQuadrant < iNumberFaces - 1 ) { EndPoint = ReferenceVertices[ iQuadrant + 1 ] * fHalfCubeWidth / 0.5; } else { EndPoint = ReferenceVertices[ 0 ] * fHalfCubeWidth / 0.5; } if( bOuter ) { face.AddPoint( StartPoint ); face.AddPoint( EndPoint ); } else { face.AddPoint( EndPoint ); face.AddPoint( StartPoint ); } return ( EndPoint - StartPoint ).length(); }
//!Copy a vector public GLVector3d(GLVector3d gv) { Buffer.BlockCopy(gv.val, 0, val, 0, Buffer.ByteLength(gv.val)); }
//!Copy a vector public GLVector3d( GLVector3d gv) { Buffer.BlockCopy( gv.val, 0, val, 0, Buffer.ByteLength( gv.val ) ); }
//!Get the dot product of this and a vector public double dot(GLVector3d gv) { return(x * gv.x + y * gv.y + z * gv.z); }
//!Get the dot product of this and a vector public double dot( GLVector3d gv) { return x*gv.x + y*gv.y + z * gv.z; }
//!Get the projection of this and a vector public double projection(GLVector3d vin) { return(dot(vin)); }
//!Get the orthogonal projection of this and a vector public GLVector3d orthogonalProjection( GLVector3d vin) { return vin - vectorProjection(vin); }
//!Get the orthogonal projection of this and a vector public GLVector3d orthogonalProjection(GLVector3d vin) { return(vin - vectorProjection(vin)); }
//!Get the vector projection of this and a vector public GLVector3d vectorProjection( GLVector3d vin) { return this * dot(vin); }
//!Get the vector projection of this and a vector public GLVector3d vectorProjection(GLVector3d vin) { return(this * dot(vin)); }
//!Apply an OpenGL scale matrix to this public GLMatrix4d applyScale( GLVector3d scale) { //improved version m[0]*=scale.x; m[1]*=scale.x; m[2]*=scale.x; m[3]*=scale.x; m[4]*=scale.y; m[5]*=scale.y; m[6]*=scale.y; m[7]*=scale.y; m[8]*=scale.z; m[9]*=scale.z; m[10]*=scale.z; m[11]*=scale.z; return this; }
//!Get the cross-product of this and a vector public GLVector3d getCross(GLVector3d gv) { return(new GLVector3d(y * gv.z - z * gv.y, z * gv.x - x * gv.z, x * gv.y - y * gv.x)); }
//!OpenGL View Matrix. public GLMatrix4d loadView( GLVector3d front, GLVector3d up, GLVector3d side) { m[0] = side.x; m[1] = up.x; m[2] = -front.x; m[3] = 0; m[4] = side.y; m[5] = up.y; m[6] = -front.y; m[7] = 0; m[8] = side.z; m[9] = up.z; m[10] = -front.z; m[11] = 0; m[12] = 0; m[13] = 0; m[14] = 0; m[15] = 1; return this; }
//! BAsically we check the quadrant, then intersect it, then we just intersect the radius with the appropriate face protected virtual GLVector3d GetCutIntersect( int iCut, double fCubeHalfWidth ) { int iCutQuadrant = GetCutQuadrant( iCut ); double fCutRatio = (double)iCut / (double)MaxCut; GLVector3d linestart = ReferenceVertices[ iCutQuadrant] * fCubeHalfWidth / 0.5; GLVector3d lineend = null; if( iCutQuadrant < iNumberFaces - 1 ) { lineend = ReferenceVertices[ iCutQuadrant + 1 ] * fCubeHalfWidth / 0.5; } else { lineend = ReferenceVertices[ 0 ] * fCubeHalfWidth / 0.5; } double fAngle = GetAngleWithXAxis( fCutRatio ); GLVector3d CutVectorPerp = new GLVector3d( - Math.Sin( fAngle ), Math.Cos( fAngle ), 0 ); // Grabbed this from http://softsurfer.com/Archive/algorithm_0104/algorithm_0104B.htm return linestart - ( lineend - linestart ) * CutVectorPerp.dot( linestart ) / CutVectorPerp.dot( lineend - linestart ); }