SVG and matrices

Started by
8 comments, last by SnotBob 15 years, 10 months ago
I am trying to implement some support for SVG in my game, actually it will only support rectangles as that's all i need. Anyways, I don't really understand matrices so I'm probably doing something terribly wrong. Anyways, this is the relevant code:

	float x, y, height, width, opacity;
	
	if (rect->QueryFloatAttribute("x", &x) != TIXML_SUCCESS)
		return;
		
	if (rect->QueryFloatAttribute("y", &y) != TIXML_SUCCESS)
		return;
		
	if (rect->QueryFloatAttribute("width", &width) != TIXML_SUCCESS)
		return;
		
	if (rect->QueryFloatAttribute("height", &height) != TIXML_SUCCESS)
		return;
		
	if (rect->QueryFloatAttribute("opacity", &opacity) != TIXML_SUCCESS)
		opacity = 0.5;

	boost::numeric::ublas::vector<float> bottom_left(3);
	// Assign x
	bottom_left[0] = x;
	// Assign y
	bottom_left[1] = y;
	// Assign z
	bottom_left[2] = 0.0;
	
	boost::numeric::ublas::vector<float> bottom_right(3);
	bottom_right[0] = x + width;
	bottom_right[1] = y;
	bottom_right[2] = 0.0;
	
	boost::numeric::ublas::vector<float> top_left(3);
	top_left[0] = x;
	top_left[1] = y + height;
	top_left[2] = 0.0;
	
	boost::numeric::ublas::vector<float> top_right(3);
	top_right[0] = x + width;
	top_right[1] = y + height;
	top_right[2] = 0.0;
		
	// transform may or may not exist
	const char * transform = rect->Attribute("transform");
	
	if (transform)
	{
		using boost::numeric::ublas::column_major;
		boost::numeric::ublas::matrix<float> matrix(3, 3);
		
		bool full = boost::spirit::parse(transform,
		( // begin grammar
			str_p("matrix(") >> real_p[ assign_a( matrix(0, 0) ) ] >> *ch_p(',') >> real_p[ assign_a( matrix(1, 0) ) ] >> *ch_p(',') >> real_p[ assign_a( matrix(0, 1) ) ] >> *ch_p(',') >> real_p[ assign_a( matrix(1, 1) ) ] >> *ch_p(',') >> real_p[ assign_a( matrix(0, 2) ) ] >> *ch_p(',') >> real_p[ assign_a( matrix(1, 2) ) ] >> ch_p(')')
		), // end grammar
		boost::spirit::space_p).full;
		
		if (!full)
			return;

		matrix(2, 0) = 0;
		matrix(2, 1) = 0;
		matrix(2, 2) = 1;
		
		
		bottom_left = boost::numeric::ublas::prod(matrix, bottom_left);
		bottom_right = boost::numeric::ublas::prod(matrix, bottom_right);
		top_left = boost::numeric::ublas::prod(matrix, top_left);
		top_right = boost::numeric::ublas::prod(matrix, top_right);
		
		/*
		bottom_left = boost::numeric::ublas::prod(bottom_left, matrix);
		bottom_right = boost::numeric::ublas::prod(bottom_right, matrix);
		top_left = boost::numeric::ublas::prod(top_left, matrix);
		top_right = boost::numeric::ublas::prod(top_right, matrix);
		*/
	}
	
	boost::shared_ptr<Rectangle> rectangle(new Rectangle);
	rectangle->bottom_left = toVec2(bottom_left);
	rectangle->bottom_right = toVec2(bottom_right);
	rectangle->top_left = toVec2(top_left);
	rectangle->top_right = toVec2(top_right);
	
	rectangles.push_back(rectangle);





I'm using boost::spirit and boost::matrix and boost::vector and TinyXML. This is how it currently looks in my engine: Free Image Hosting at www.ImageShack.us And this is how it should look: Free Image Hosting at www.ImageShack.us Note: Color is not implemented yet. The relevant svg spec about matrices is here: http://www.w3.org/TR/SVG11/coords.html#TransformMatrixDefined The used .svg file is here: http://rafb.net/p/zMYK1889.html As you can see the rectangles that doesn't use matrices look correct but those who does looks wrong. (My matrix math is probably wrong) EDIT: Um, i changed the z coord of the start vectors to 1.0 and it seems to look okay but the .svg is flipped upside down. And clues? EDIT2: I have the same base .svg orginally exported from Illustrator instead of Inkscape and it still doesn't look correct: Free Image Hosting at www.ImageShack.us Svg is here: http://rafb.net/p/MuGjZL59.html [Edited by - lexs on May 28, 2008 2:59:22 PM]
Advertisement
Noone?
If it's flipped upside down, you're probably just using the wrong coordinate system. Just flip the Y-axis. And yes, the 'Z' coordinates do need to be set to 1, otherwise the coordinates do not get translated, only rotated.
It renders correctly now (I was not aware that the svg spec didn't require x and y coords).
But it's still upside down. Simply flipping the Y will give wrong results:


Free Image Hosting at www.ImageShack.us

This image is how it looks now, with the green dot being (0,0) in the svg image. It is correctly situated and the lower left corner. If I flip the Y axis it will instead be in the top left corner.
Then maybe you're reading the matrix wrong. Try placing an object that's not rotated by 45 degrees into the SVG. E.g. rotate by 25 degrees. If it renders at a wrong angle, then you're reading the elements of the matrix into incorrect locations.
Made a .svg with two rectangles rotated by 25 deg and -25 deg:

Free Image Hosting at www.ImageShack.us

Seems to render correctly, just upside down :)
So only the rectangles are upside down, even the ones that don't have the transform attribute? But the green dot isn't? How does the SVG differ for the two?
Yeah. The dot I render manually. I think I have something wrong in my Rect->VBO code (not posted). Will check it and report back ;)
Damn, you were right from the beginning. The origin in SVG is top left so flipping Y is correct.
Thanks!
It seems that the SVG origin is in the top-left corner, so even your green dot is upside down. Viewport

This topic is closed to new replies.

Advertisement