Esempio n. 1
0
	//--------------------------------------------------------------------------------------------------------------
	//获取该矢量的长度
	float Vector2::GetLength() const
	{
		return Vec2Length( this );
	}
Esempio n. 2
0
/* draw a given stroke in 2d */
static void gp_draw_stroke (bGPDspoint *points, int totpoints, short thickness, short dflag, short sflag, 
							short debug, int offsx, int offsy, int winx, int winy)
{
	/* if thickness is less than GP_DRAWTHICKNESS_SPECIAL, 'smooth' opengl lines look better
	 * 	- 'smooth' opengl lines are also required if Image Editor 'image-based' stroke
	 */
	if ( (thickness < GP_DRAWTHICKNESS_SPECIAL) || 
		 ((dflag & GP_DRAWDATA_IEDITHACK) && (dflag & GP_DRAWDATA_ONLYV2D)) ) 
	{
		bGPDspoint *pt;
		int i;
		
		glBegin(GL_LINE_STRIP);
		for (i=0, pt=points; i < totpoints && pt; i++, pt++) {
			if (sflag & GP_STROKE_2DSPACE) {
				glVertex2f(pt->x, pt->y);
			}
			else if (sflag & GP_STROKE_2DIMAGE) {
				const float x= (pt->x * winx) + offsx;
				const float y= (pt->y * winy) + offsy;
				
				glVertex2f(x, y);
			}
			else {
				const float x= (pt->x / 100 * winx);
				const float y= (pt->y / 100 * winy);
				
				glVertex2f(x, y);
			}
		}
		glEnd();
	}
	
	/* tesselation code - draw stroke as series of connected quads with connection
	 * edges rotated to minimise shrinking artifacts, and rounded endcaps
	 */
	else 
	{ 
		bGPDspoint *pt1, *pt2;
		float pm[2];
		int i;
		
		glShadeModel(GL_FLAT);
		glBegin(GL_QUADS);
		
		for (i=0, pt1=points, pt2=points+1; i < (totpoints-1); i++, pt1++, pt2++) {
			float s0[2], s1[2];		/* segment 'center' points */
			float t0[2], t1[2];		/* tesselated coordinates */
			float m1[2], m2[2];		/* gradient and normal */
			float mt[2], sc[2];		/* gradient for thickness, point for end-cap */
			float pthick;			/* thickness at segment point */
			
			/* get x and y coordinates from points */
			if (sflag & GP_STROKE_2DSPACE) {
				s0[0]= pt1->x; 		s0[1]= pt1->y;
				s1[0]= pt2->x;		s1[1]= pt2->y;
			}
			else if (sflag & GP_STROKE_2DIMAGE) {
				s0[0]= (pt1->x * winx) + offsx; 		
				s0[1]= (pt1->y * winy) + offsy;
				s1[0]= (pt2->x * winx) + offsx;		
				s1[1]= (pt2->y * winy) + offsy;
			}
			else {
				s0[0]= (pt1->x / 100 * winx);
				s0[1]= (pt1->y / 100 * winy);
				s1[0]= (pt2->x / 100 * winx);
				s1[1]= (pt2->y / 100 * winy);
			}		
			
			/* calculate gradient and normal - 'angle'=(ny/nx) */
			m1[1]= s1[1] - s0[1];		
			m1[0]= s1[0] - s0[0];
			Normalize2(m1);
			m2[1]= -m1[0];
			m2[0]= m1[1];
			
			/* always use pressure from first point here */
			pthick= (pt1->pressure * thickness);
			
			/* if the first segment, start of segment is segment's normal */
			if (i == 0) {
				/* draw start cap first 
				 *	- make points slightly closer to center (about halfway across) 
				 */				
				mt[0]= m2[0] * pthick * 0.5f;
				mt[1]= m2[1] * pthick * 0.5f;
				sc[0]= s0[0] - (m1[0] * pthick * 0.75f);
				sc[1]= s0[1] - (m1[1] * pthick * 0.75f);
				
				t0[0]= sc[0] - mt[0];
				t0[1]= sc[1] - mt[1];
				t1[0]= sc[0] + mt[0];
				t1[1]= sc[1] + mt[1];
				
				glVertex2fv(t0);
				glVertex2fv(t1);
				
				/* calculate points for start of segment */
				mt[0]= m2[0] * pthick;
				mt[1]= m2[1] * pthick;
				
				t0[0]= s0[0] - mt[0];
				t0[1]= s0[1] - mt[1];
				t1[0]= s0[0] + mt[0];
				t1[1]= s0[1] + mt[1];
				
				/* draw this line twice (first to finish off start cap, then for stroke) */
				glVertex2fv(t1);
				glVertex2fv(t0);
				glVertex2fv(t0);
				glVertex2fv(t1);
			}
			/* if not the first segment, use bisector of angle between segments */
			else {
				float mb[2]; 		/* bisector normal */
				float athick, dfac;		/* actual thickness, difference between thicknesses */
				
				/* calculate gradient of bisector (as average of normals) */
				mb[0]= (pm[0] + m2[0]) / 2;
				mb[1]= (pm[1] + m2[1]) / 2;
				Normalize2(mb);
				
				/* calculate gradient to apply 
				 * 	- as basis, use just pthick * bisector gradient
				 *	- if cross-section not as thick as it should be, add extra padding to fix it
				 */
				mt[0]= mb[0] * pthick;
				mt[1]= mb[1] * pthick;
				athick= Vec2Length(mt);
				dfac= pthick - (athick * 2);
				if ( ((athick * 2) < pthick) && (IS_EQ(athick, pthick)==0) ) 
				{
					mt[0] += (mb[0] * dfac);
					mt[1] += (mb[1] * dfac);
				}	
				
				/* calculate points for start of segment */
				t0[0]= s0[0] - mt[0];
				t0[1]= s0[1] - mt[1];
				t1[0]= s0[0] + mt[0];
				t1[1]= s0[1] + mt[1];
				
				/* draw this line twice (once for end of current segment, and once for start of next) */
				glVertex2fv(t1);
				glVertex2fv(t0);
				glVertex2fv(t0);
				glVertex2fv(t1);
			}
			
			/* if last segment, also draw end of segment (defined as segment's normal) */
			if (i == totpoints-2) {
				/* for once, we use second point's pressure (otherwise it won't be drawn) */
				pthick= (pt2->pressure * thickness);
				
				/* calculate points for end of segment */
				mt[0]= m2[0] * pthick;
				mt[1]= m2[1] * pthick;
				
				t0[0]= s1[0] - mt[0];
				t0[1]= s1[1] - mt[1];
				t1[0]= s1[0] + mt[0];
				t1[1]= s1[1] + mt[1];
				
				/* draw this line twice (once for end of stroke, and once for endcap)*/
				glVertex2fv(t1);
				glVertex2fv(t0);
				glVertex2fv(t0);
				glVertex2fv(t1);
				
				
				/* draw end cap as last step 
				 *	- make points slightly closer to center (about halfway across) 
				 */				
				mt[0]= m2[0] * pthick * 0.5f;
				mt[1]= m2[1] * pthick * 0.5f;
				sc[0]= s1[0] + (m1[0] * pthick * 0.75f);
				sc[1]= s1[1] + (m1[1] * pthick * 0.75f);
				
				t0[0]= sc[0] - mt[0];
				t0[1]= sc[1] - mt[1];
				t1[0]= sc[0] + mt[0];
				t1[1]= sc[1] + mt[1];
				
				glVertex2fv(t1);
				glVertex2fv(t0);
			}
			
			/* store stroke's 'natural' normal for next stroke to use */
			Vec2Copyf(pm, m2);
		}
		
		glEnd();
	}
	
	/* draw debug points of curve on top? (original stroke points) */
	if (debug) {
		bGPDspoint *pt;
		int i;
		
		glBegin(GL_POINTS);
		for (i=0, pt=points; i < totpoints && pt; i++, pt++) {
			if (sflag & GP_STROKE_2DSPACE) {
				glVertex2f(pt->x, pt->y);
			}
			else if (sflag & GP_STROKE_2DIMAGE) {
				const float x= (float)((pt->x * winx) + offsx);
				const float y= (float)((pt->y * winy) + offsy);
				
				glVertex2f(x, y);
			}
			else {
				const float x= (float)(pt->x / 100 * winx);
				const float y= (float)(pt->y / 100 * winy);
				
				glVertex2f(x, y);
			}
		}
		glEnd();
	}
}
void MeshParameterization::GenerateTriangleTexelData()
{
#if ENABLE_DEBUG_DEGENERATES
	
	map< float, blah > s_DegenerateList;
#endif
	//Generate texel data per triangle
	const float uIncrement = 1.f/(float)m_TexSize;
	const float vIncrement = 1.f/(float)m_TexSize;
	const float uHalfIncrement = uIncrement*.5f;
	const float vHalfIncrement =  vIncrement*.5f;
	ParameterizationVertex * p0;
	ParameterizationVertex * p1;
	ParameterizationVertex * p2;
	//0 is smallest y value
	//1 is smallest x value that's not 0
	TriangleTextureMapping toAdd;
	Vec3 barycentric;
	float u;
	float uMax;
	for( int i = 0; i < (int)m_Faces->size(); i++ )
	{
		TriangleFace &tri = (*m_Faces)[ i ];
		bool DangerTriangle = false;
		//get verts
		p0 = &(*m_CollapsedMesh)[ tri.index[ 0 ] ];
		p1 = &(*m_CollapsedMesh)[ tri.index[ 1 ] ];
		p2 = &(*m_CollapsedMesh)[ tri.index[ 2 ] ];
		
		NormalizeUV( p1->generatedU );
		NormalizeUV( p1->generatedV );
		NormalizeUV( p2->generatedU );
		NormalizeUV( p2->generatedV );
		NormalizeUV( p0->generatedU );
		NormalizeUV( p0->generatedV );
		if( p0->generatedV > p1->generatedV )
		{
			SwapPointers( &p0, &p1 ); 
		}
		if( p0->generatedV > p2->generatedV )
		{ 
			SwapPointers( &p0, &p2 );
		}
		if( p1->generatedU > p2->generatedU )
		{
			SwapPointers( &p1, &p2 ); 
		}			
		//find slopes
		float slope1, slope2, slope3, slope4;
		bool undefinedSlope[4];
		undefinedSlope[0] = false;
		undefinedSlope[1] = false;
		undefinedSlope[2] = false;
		undefinedSlope[3] = false;
		if( fabs( p0->generatedV - p1->generatedV ) <= EPSILON_ZERO )
		{ 
			undefinedSlope[0] = true; 
		}
		if( fabs( p0->generatedV - p2->generatedV ) <= EPSILON_ZERO )
		{ 
			undefinedSlope[1] = true;
		}
		if( fabs( p1->generatedV - p2->generatedV ) <= EPSILON_ZERO )
		{
			undefinedSlope[2] = true; 
		}
		if( fabs( p2->generatedV - p1->generatedV ) <= EPSILON_ZERO )
		{ 
			undefinedSlope[3] = true;
		}
		slope1 = ( p0->generatedU - p1->generatedU )/(p0->generatedV - p1->generatedV );
		slope2 = ( p0->generatedU - p2->generatedU )/(p0->generatedV - p2->generatedV );
		slope3 = ( p1->generatedU - p2->generatedU )/(p1->generatedV - p2->generatedV );
		slope4 = ( p2->generatedU - p1->generatedU )/(p2->generatedV - p1->generatedV );
		float maxV = ( p1->generatedV > p2->generatedV ) ? p1->generatedV : p2->generatedV;
		float maxU = ( p0->generatedU > p2->generatedU ) ? p0->generatedU : p2->generatedU;
		maxU += uIncrement;
		maxV += vHalfIncrement;
		for( float v = p0->generatedV - vHalfIncrement; v <= maxV ; v += vIncrement )
		{
			if( p1->generatedV >= v &&
				p2->generatedV >= v )
			{
				//find endpoints of scanline				
				u = undefinedSlope[0] ?  p1->generatedU : p1->generatedU + slope1*( v - p1->generatedV ) - uHalfIncrement;
				uMax = undefinedSlope[1] ? p2->generatedU : p2->generatedU + slope2*( v - p2->generatedV ) + uHalfIncrement;
			}
			else if( p2->generatedV <= v )
			{
				//find endpoints of scanline
				u = undefinedSlope[0] ? p1->generatedU : p1->generatedU + slope1*( v - p1->generatedV )- uHalfIncrement;
				uMax = undefinedSlope[3] ? p2->generatedU : p1->generatedU + slope4*( v - p1->generatedV ) + uHalfIncrement;
			}
			else // p1->v is smaller than v, we're need a new edge
			{
				//find endpoints of scanline
				u =  undefinedSlope[2] ? p1->generatedU : p2->generatedU + slope3*( v - p2->generatedV ) - uHalfIncrement;
				uMax =  undefinedSlope[1] ? p2->generatedU : p2->generatedU + slope2*( v - p2->generatedV ) + uHalfIncrement;
			}
			if( u > uMax ){ float temp = u; u = uMax; uMax = temp; }
			uMax = min( uMax, maxU );
			float umin = min( p1->generatedU, p0->generatedU - uIncrement);
			u = max( u, umin);
			for( ; u <= uMax; u+= uIncrement )
			{
				//we have u and v, get barycentric: 				
				//check if slope will be undefined
				float qX, qY;
				float slopeBC, b2, b1, slope;
				float slopeDenom = u - p0->generatedU;
				float slopeDenom2 = p1->generatedU - p2->generatedU;
				if( slopeDenom == 0 &&
					slopeDenom2 != 0)
				{
                    //vertical line, we know x coordinate
					slopeBC = ( p1->generatedV - p2->generatedV )/( p1->generatedU - p2->generatedU );
					b2 = p1->generatedV - slopeBC*p1->generatedU;
					//solve for y with known x coordinate
					qX = p0->generatedU;
					qY = slopeBC*qX + b2;
				}else if( slopeDenom2 != 0 &&
					slopeDenom != 0 )
				{
					slope = ( v - p0->generatedV )/slopeDenom;
					//find other slope, will never be undefined
					slopeBC = ( p1->generatedV - p2->generatedV )/( p1->generatedU - p2->generatedU );
					//now solve for intersect
					b1 = v - slope*u;
					b2 = p1->generatedV - slopeBC*p1->generatedU;
					qX = ( b1 - b2 )/(slopeBC - slope);
					qY = slope*qX + b1;
					//now find length for bary
				}else if( slopeDenom2 == 0 && slopeDenom != 0 )
				{
					slope = ( v - p0->generatedV )/slopeDenom;
					//now solve for intersect
					b1 = v - slope*u;
					qX = p2->generatedU;
					qY = slope*qX + b1;
					//now find length for bary
				}else //both equal 0
				{
					//this should never happen!
					OutputDebugString("Slopes of two triangle sides are both zero!!!\n");
					qX = p2->generatedU;
					qY = p2->generatedV;
				}
				barycentric.z = Vec2Length( p1->generatedU - qX, p1->generatedV - qY );
				barycentric.y = Vec2Length( p2->generatedU - qX, p2->generatedV - qY );
				//now find t to balance these out at q on p
				float ratio =  Vec2Length( qX - u, qY - v ) 
								/Vec2Length( u - p0->generatedU, v - p0->generatedV);
                barycentric.x = ( barycentric.y + barycentric.z )*ratio;

				float normalize = barycentric.x + barycentric.y + barycentric.z;
				if( normalize != 0 )
				{
					barycentric.x /= normalize;
					barycentric.y /= normalize;
					barycentric.z /= normalize;

					toAdd.localSpaceCoord = p0->originalPosition*barycentric.x + 
											p1->originalPosition*barycentric.y + 
											p2->originalPosition*barycentric.z;		
					
					if( toAdd.localSpaceCoord.x != toAdd.localSpaceCoord.x )
					{
						DangerTriangle = true;
						//OutputDebugString( "DANGER WILL ROBINSON\n");
					}
					toAdd.localNormal = p0->normal*barycentric.x + 
										p1->normal*barycentric.y + 
										p2->normal*barycentric.z;
					
					toAdd.u = (int)( u*(float)m_TexSize );
					toAdd.v = (int)( v*(float)m_TexSize );
					if( toAdd.localSpaceCoord.x == toAdd.localSpaceCoord.x &&
						toAdd.u >= 0 && toAdd.u < m_TexSize &&
						toAdd.v >= 0 && toAdd.v < m_TexSize )
					{
						tri.m_Pixels.push_back( toAdd );
					}
				}
									
			}
			static int numcont = 0;
			numcont++;
			if( DangerTriangle &&
				numcont < 200 )
			{
				ADDLINEPARAMS LineParam;
				static CHashString h(_T("none"));
				LineParam.name = &h;
				LineParam.blue = 0;
				LineParam.green = 0;
				LineParam.red = 255;
				LineParam.start = p0->originalPosition;
				LineParam.end = p1->originalPosition;
				//static DWORD msgHash_AddLine = CHashString(_T("AddLine")).GetUniqueID();
				//EngineGetToolBox()->SendMessage(msgHash_AddLine,sizeof(LineParam), &LineParam );
				LineParam.start = p0->originalPosition;
				LineParam.end = p2->originalPosition;
				//EngineGetToolBox()->SendMessage(msgHash_AddLine,sizeof(LineParam), &LineParam );
				LineParam.start = p2->originalPosition;
				LineParam.end = p1->originalPosition;
				//EngineGetToolBox()->SendMessage(msgHash_AddLine,sizeof(LineParam), &LineParam );
			}
		}
		//test code
#if ENABLE_DEBUG_DEGENERATES
		Vec3 edge1 = Vec3( p0->generatedU, p0->generatedV, 0 ) - Vec3( p1->generatedU, p1->generatedV, 0 );
		Vec3 edge2 = Vec3( p0->generatedU, p0->generatedV, 0 ) - Vec3( p2->generatedU, p2->generatedV, 0 );
		float lengthA = edge1.Length();
		float lengthB = (Vec3( p1->generatedU, p1->generatedV, 0 ) - Vec3( p2->generatedU, p2->generatedV, 0 )).Length();
		float lengthC = edge2.Length();
		float halfPerimeter = (lengthA + lengthB + lengthC)*.500f;
		float area = halfPerimeter*( halfPerimeter - lengthA )*(halfPerimeter - lengthB )*(halfPerimeter - lengthC);
		area = sqrt( area );
		float numPixels = (float)tri.m_Pixels.size();
		edge1.Normalize();
		edge2.Normalize();
		float flatTriangle = edge2.Dot( edge1 );
		//if( fabs( flatTriangle ) < .7f)
		{
			area *= (float)(m_TexSize*m_TexSize);
			float areaRatio = numPixels/area;
			if( areaRatio < .8f ) //half the uv pixels aren't generate?!#!
			{
				blah ref;
				ref.area = area;
				ref.pixels = (int)numPixels;
				ref.index = i;
				s_DegenerateList.insert( pair< float, blah >( numPixels, ref ) );
			}
		}
#endif
		if( tri.m_Pixels.size() < 2)
		{
			//something wrong here
			//OutputDebugString("Degenerate Triangle\n");
			//OutputVector( p0->originalPosition, "p0" );
			//OutputVector( p1->originalPosition, "p1" );
			//OutputVector( p2->originalPosition, "p2" );
			//int a = 0;
		}
	}	
#if ENABLE_DEBUG_DEGENERATES
	static char buf[1024];
	for( map< float, blah >::iterator iter = s_DegenerateList.begin();
		iter != s_DegenerateList.end();
		++iter )
	{
		blah &ref = iter->second;
		TriangleFace &tri = (*m_Faces)[ ref.index  ];
		//get verts
		p0 = &(*m_CollapsedMesh)[ tri.index[ 0 ] ];
		p1 = &(*m_CollapsedMesh)[ tri.index[ 1 ] ];
		p2 = &(*m_CollapsedMesh)[ tri.index[ 2 ] ];		
		//sprintf( buf, "Degenerate Triangle with area: %f, pixels: %d, index: %d \n", ref.area, ref.pixels, ref.index );
		//OutputDebugString( buf );
		//OutputVector( p0->originalPosition, "p0" );
		//OutputVector( p1->originalPosition, "p1" );
		//OutputVector( p2->originalPosition, "p2" );
		ADDLINEPARAMS LineParam;
		static CHashString h(_T("none"));
		LineParam.name = &h;
		LineParam.blue = 0;
		LineParam.green = 0;
		LineParam.red = 255;
		LineParam.start = p0->originalPosition;
		LineParam.end = p1->originalPosition;
		static DWORD msgHash_AddLine = CHashString(_T("AddLine")).GetUniqueID();
		EngineGetToolBox()->SendMessage(msgHash_AddLine,sizeof(LineParam), &LineParam );
		LineParam.start = p0->originalPosition;
		LineParam.end = p2->originalPosition;
		static DWORD msgHash_AddLine = CHashString(_T("AddLine")).GetUniqueID();
		EngineGetToolBox()->SendMessage(msgHash_AddLine,sizeof(LineParam), &LineParam );
		LineParam.start = p2->originalPosition;
		LineParam.end = p1->originalPosition;
		static DWORD msgHash_AddLine = CHashString(_T("AddLine")).GetUniqueID();
		EngineGetToolBox()->SendMessage(msgHash_AddLine,sizeof(LineParam), &LineParam );
	}
#endif
}