Jason McKesson avatar Jason McKesson committed 0fdfb8b

Added almost all of the images for Tutorial 06.

Comments (0)

Files changed (14)

Add a comment to this file

Documents/Positioning/CoordSys2D.svg

Added
New image
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" height="700px" width="300px" >
+	<style type="text/css" ><![CDATA[.x_axis
+{
+	marker-end: url(#big_arrow_x_axis);
+	stroke: green;
+	stroke-width: 3px;
+}
+
+.thin
+{
+	stroke-width: 1px;
+}
+
+.x_axis_marker
+{
+	stroke: green;
+	stroke-width: 3px;
+	fill: none;
+}
+
+.arrow_end
+{
+	marker-end: url(#arrow);
+}
+
+.wide
+{
+	stroke-width: 2px;
+}
+
+.y_axis_marker
+{
+	stroke: red;
+	stroke-width: 3px;
+	fill: none;
+}
+
+.fill_none
+{
+	fill: none;
+}
+
+.fill_black
+{
+	fill: black;
+}
+
+.line_currColor
+{
+	stroke: currentColor;
+}
+
+.y_axis
+{
+	marker-end: url(#big_arrow_y_axis);
+	stroke: red;
+	stroke-width: 3px;
+}
+
+.black
+{
+	stroke: black;
+}]]></style>
+	<defs >
+		<marker markerWidth="10" markerHeight="10" refX="5" refY="5" markerUnits="userSpaceOnUse" orient="auto" id="point" >
+			<circle r="5" cy="5" cx="5" class="fill_black black" />
+		</marker>
+		<marker markerWidth="10" markerHeight="8" refX="10" refY="4" markerUnits="userSpaceOnUse" orient="auto" id="arrow" >
+			<path d="M 10 4 L 0 0 L 0 8 Z" class="fill_black thin" />
+		</marker>
+		<marker markerWidth="10" markerHeight="20" refX="10" refY="10" markerUnits="userSpaceOnUse" orient="auto" id="big_arrow_y_axis" >
+			<path d="M 0 0 L 10 10 L 0 20" class="y_axis_marker" />
+		</marker>
+		<marker markerWidth="10" markerHeight="20" refX="10" refY="10" markerUnits="userSpaceOnUse" orient="auto" id="big_arrow_x_axis" >
+			<path d="M 0 0 L 10 10 L 0 20" class="x_axis_marker" />
+		</marker>
+	</defs>
+	<line x2="150" y2="300" y1="150" x1="150" class="black thin arrow_end" />
+	<line x2="150" y2="0" y1="150" x1="150" class="black thin arrow_end" />
+	<line x2="300" y2="150" y1="150" x1="150" class="black thin arrow_end" />
+	<line x2="0" y2="150" y1="150" x1="150" class="black thin arrow_end" />
+	<line x2="187.5" y2="150" y1="150" x1="150" class="x_axis" />
+	<line x2="225" y2="150" y1="150" x1="187.5" class="x_axis" />
+	<circle r="5" cy="75" cx="225" class="fill_black black" />
+	<line x2="225" y2="112.5" y1="150" x1="225" class="y_axis" />
+	<line x2="225" y2="75" y1="112.5" x1="225" class="y_axis" />
+	<line x2="111.17714323462" y2="694.88887394336" y1="550" x1="150" class="black thin arrow_end" />
+	<line x2="188.82285676538" y2="405.11112605664" y1="550" x1="150" class="black thin arrow_end" />
+	<line x2="294.88887394336" y2="511.17714323462" y1="550" x1="150" class="black thin arrow_end" />
+	<line x2="5.1111260566398" y2="588.82285676538" y1="550" x1="150" class="black thin arrow_end" />
+	<line x2="186.22221848584" y2="540.29428580866" y1="550" x1="150" class="x_axis" />
+	<line x2="222.44443697168" y2="530.58857161731" y1="540.29428580866" x1="186.22221848584" class="x_axis" />
+	<circle r="5" cy="458.14413464563" cx="241.85586535437" class="fill_black black" />
+	<line x2="232.15015116302" y2="494.36635313147" y1="530.58857161731" x1="222.44443697168" class="y_axis" />
+	<line x2="241.85586535437" y2="458.14413464563" y1="494.36635313147" x1="232.15015116302" class="y_axis" />
+</svg>

Documents/Positioning/GenCoordSys2D.lua

+require "SvgWriter"
+require "vmath"
+require "Viewport"
+require "SubImage"
+
+local subImages = SubImage.SubImage(1, 2, 300, 300, 0, 100);
+
+local coordSize = 8;
+local dotRadius = 5;
+
+local vp = Viewport.Viewport({300, 300}, {0, 0}, coordSize)
+local trans2 = Viewport.Transform2D()
+vp:SetTransform(trans2);
+
+-- Styles
+local styleLib = SvgWriter.StyleLibrary();
+local pointSize = 10;
+
+styleLib:AddStyle(nil, "black",
+	SvgWriter.Style():stroke("black"));
+	
+styleLib:AddStyle(nil, "x_axis_marker",
+	SvgWriter.Style():stroke("green"):fill("none"):stroke_width("3px"));
+	
+styleLib:AddStyle(nil, "y_axis_marker",
+	SvgWriter.Style():stroke("red"):fill("none"):stroke_width("3px"));
+	
+styleLib:AddStyle(nil, "x_axis",
+	SvgWriter.Style():stroke("green"):stroke_width("3px"):marker_end(SvgWriter.uriLocalElement("big_arrow_x_axis")));
+	
+styleLib:AddStyle(nil, "y_axis",
+	SvgWriter.Style():stroke("red"):stroke_width("3px"):marker_end(SvgWriter.uriLocalElement("big_arrow_y_axis")));
+	
+styleLib:AddStyle(nil, "wide",
+	SvgWriter.Style():stroke_width("2px"));
+	
+styleLib:AddStyle(nil, "thin",
+	SvgWriter.Style():stroke_width("1px"));
+
+styleLib:AddStyle(nil, "fill_black",
+	SvgWriter.Style():fill("black"));
+	
+styleLib:AddStyle(nil, "fill_none",
+	SvgWriter.Style():fill("none"));
+
+styleLib:AddStyle(nil, "arrow_end",
+	SvgWriter.Style():marker_end(SvgWriter.uriLocalElement("arrow")));
+
+local arrowheadPath = SvgWriter.Path();
+arrowheadPath:M{10, 4}:L{0, 0}:L{0, 8}:Z();
+
+local bigArrowheadPath = SvgWriter.Path();
+bigArrowheadPath:M{0, 0}:L{10, 10}:L{0, 20};
+
+--Generate axes.
+local axes = {};
+
+local upperBound, lowerBound = vp:Extents();
+axes[#axes + 1] = vmath.vec2((upperBound[1] + lowerBound[1]) / 2, 0);
+axes[#axes + 1] = vmath.vec2((upperBound[1] + lowerBound[1]) / 2, lowerBound[2]);
+axes[#axes + 1] = vmath.vec2((upperBound[1] + lowerBound[1]) / 2, 0);
+axes[#axes + 1] = vmath.vec2((upperBound[1] + lowerBound[1]) / 2, upperBound[2]);
+axes[#axes + 1] = vmath.vec2(0, (upperBound[2] + lowerBound[2]) / 2);
+axes[#axes + 1] = vmath.vec2(upperBound[1], (upperBound[2] + lowerBound[2]) / 2);
+axes[#axes + 1] = vmath.vec2(0, (upperBound[2] + lowerBound[2]) / 2);
+axes[#axes + 1] = vmath.vec2(lowerBound[1], (upperBound[2] + lowerBound[2]) / 2);
+
+--Draw Coordinate.
+local coordsX = {};
+local coordsY = {};
+
+coordsX[#coordsX + 1] = vmath.vec2(0, 0);
+coordsX[#coordsX + 1] = vmath.vec2(1, 0);
+coordsX[#coordsX + 1] = vmath.vec2(1, 0);
+coordsX[#coordsX + 1] = vmath.vec2(2, 0);
+
+coordsY[#coordsY + 1] = vmath.vec2(2, 0);
+coordsY[#coordsY + 1] = vmath.vec2(2, 1);
+coordsY[#coordsY + 1] = vmath.vec2(2, 1);
+coordsY[#coordsY + 1] = vmath.vec2(2, 2);
+
+
+local writer = SvgWriter.SvgWriter("CoordSys2D.svg", {subImages:Size().x .."px", subImages:Size().y .. "px"});
+	writer:StyleLibrary(styleLib);
+	writer:BeginDefinitions();
+		writer:BeginMarker({pointSize, pointSize}, {pointSize/2, pointSize/2}, "auto", true, nil, "point");
+			writer:Circle({pointSize/2, pointSize/2}, pointSize/2, {"fill_black", "black"});
+		writer:EndMarker();
+		writer:BeginMarker({10, 8}, {10, 4}, "auto", true, nil, "arrow");
+			writer:Path(arrowheadPath, {"fill_black", "thin"});
+		writer:EndMarker();
+		writer:BeginMarker({10, 20}, {10, 10}, "auto", true, nil, "big_arrow_y_axis");
+			writer:Path(bigArrowheadPath, {"y_axis_marker"});
+		writer:EndMarker();
+		writer:BeginMarker({10, 20}, {10, 10}, "auto", true, nil, "big_arrow_x_axis");
+			writer:Path(bigArrowheadPath, {"x_axis_marker"});
+		writer:EndMarker();
+	writer:EndDefinitions();
+
+	--Draw the axes for the regular coord system.
+	local topAxes = subImages:Transform({1, 1}, vp:Transform(axes))
+	for i=1, #axes, 2 do
+		writer:Line(topAxes[i], topAxes[i + 1], {"black", "thin", "arrow_end"});
+	end
+	
+	local topCoordX = subImages:Transform({1, 1}, vp:Transform(coordsX))
+	for i=1, #topCoordX, 2 do
+		writer:Line(topCoordX[i], topCoordX[i + 1], {"x_axis"});
+	end
+	
+	local topCoordY = subImages:Transform({1, 1}, vp:Transform(coordsY))
+	writer:Circle(topCoordY[#topCoordY], dotRadius, {"fill_black", "black"});
+	for i=1, #topCoordY, 2 do
+		writer:Line(topCoordY[i], topCoordY[i + 1], {"y_axis"});
+	end
+	
+
+	
+	--Setup the skewed coordinate system.
+	local basisVectors = {};
+	local tempTrans = Viewport.Transform2D()
+	tempTrans:Rotate(-15);
+	basisVectors[1] = tempTrans:Matrix():Transform(vmath.vec2(1, 0));
+	tempTrans:Identity();
+	tempTrans:Rotate(15);
+	basisVectors[2] = tempTrans:Matrix():Transform(vmath.vec2(0, 1));
+	tempTrans:Identity();
+	
+	local transformMatrix = tempTrans:Matrix();
+	tempTrans:Identity();
+	transformMatrix:SetCol(1, vmath.vec3(basisVectors[1], 0.0));
+	transformMatrix:SetCol(2, vmath.vec3(basisVectors[2], 0.0));
+	
+	--Draw the axes for the skewed coord system.
+	trans2:MultMatrix(transformMatrix);
+	local botAxes = subImages:Transform({1, 2}, vp:Transform(axes))
+	for i=1, #axes, 2 do
+		writer:Line(botAxes[i], botAxes[i + 1], {"black", "thin", "arrow_end"});
+	end
+	
+	local botCoordX = subImages:Transform({1, 2}, vp:Transform(coordsX))
+	for i=1, #botCoordX, 2 do
+		writer:Line(botCoordX[i], botCoordX[i + 1], {"x_axis"});
+	end
+	
+	local botCoordY = subImages:Transform({1, 2}, vp:Transform(coordsY))
+	writer:Circle(botCoordY[#topCoordY], dotRadius, {"fill_black", "black"});
+	for i=1, #botCoordY, 2 do
+		writer:Line(botCoordY[i], botCoordY[i + 1], {"y_axis"});
+	end
+	
+writer:Close();

Documents/Positioning/GenRotationTransform.lua

+require "SvgWriter"
+require "vmath"
+require "Viewport"
+require "SubImage"
+
+local subImages = SubImage.SubImage(2, 1, 300, 300, 100, 0);
+
+local coordSize = 8;
+
+local vp = Viewport.Viewport({300, 300}, {0, 0}, coordSize)
+local trans2 = Viewport.Transform2D()
+vp:SetTransform(trans2);
+
+-- Styles
+local styleLib = SvgWriter.StyleLibrary();
+local pointSize = 10;
+
+local coordAxisWidth = "2px";
+local xCoordAxisColor = "green";
+local yCoordAxisColor = "red";
+local objectColor = "#AFAFFF";
+
+styleLib:AddStyle(nil, "black",
+	SvgWriter.Style():stroke("black"));
+	
+styleLib:AddStyle(nil, "grid",
+	SvgWriter.Style():stroke("#CCC"):fill("none"):stroke_width("1px"));
+
+styleLib:AddStyle(nil, "axes",
+	SvgWriter.Style():stroke("black"):fill("none"):stroke_width("2px")
+		:marker_end(SvgWriter.uriLocalElement("arrow")));
+
+styleLib:AddStyle(nil, "point",
+	SvgWriter.Style():stroke(objectColor):fill(objectColor));
+	
+styleLib:AddStyle(nil, "triangle",
+	SvgWriter.Style():stroke(objectColor):stroke_width("2px"):fill("none")
+		:marker(SvgWriter.uriLocalElement("m_point")));
+	
+styleLib:AddStyle(nil, "x_axis",
+	SvgWriter.Style():stroke(xCoordAxisColor):stroke_width(coordAxisWidth):fill("none")
+		:marker_end(SvgWriter.uriLocalElement("big_arrow_x_axis")));
+	
+styleLib:AddStyle(nil, "y_axis",
+	SvgWriter.Style():stroke(yCoordAxisColor):stroke_width(coordAxisWidth):fill("none")
+		:marker_end(SvgWriter.uriLocalElement("big_arrow_y_axis")));
+	
+styleLib:AddStyle(nil, "x_axis_marker",
+	SvgWriter.Style():stroke(xCoordAxisColor):stroke_width(coordAxisWidth):fill("none"));
+
+styleLib:AddStyle(nil, "y_axis_marker",
+	SvgWriter.Style():stroke(yCoordAxisColor):stroke_width(coordAxisWidth):fill("none"));
+
+styleLib:AddStyle(nil, "arrow_end",
+	SvgWriter.Style():marker_end(SvgWriter.uriLocalElement("arrow")));
+
+local arrowheadPath = SvgWriter.Path();
+arrowheadPath:M{10, 4}:L{0, 0}:L{0, 8}:Z();
+
+local bigArrowheadPath = SvgWriter.Path();
+bigArrowheadPath:M{0, 0}:L{10, 10}:L{0, 20};
+
+--Generate grid.
+local upperBound, lowerBound = vp:Extents();
+
+local gridPath = SvgWriter.Path();
+
+--Vertical lines.
+for i = lowerBound[1], upperBound[1] do
+	local points =
+	{
+		vmath.vec2(i, lowerBound[2]);
+		vmath.vec2(i, upperBound[2]);
+	};
+	
+	points = vp:Transform(points)
+	gridPath:M(points[1]):V(points[2][2]);
+end
+
+--Horizontal lines.
+for i = lowerBound[2], upperBound[2] do
+	local points =
+	{
+		vmath.vec2(lowerBound[1], i);
+		vmath.vec2(upperBound[1], i);
+	};
+	
+	points = vp:Transform(points)
+	gridPath:M(points[1]):H(points[2][1]);
+end
+
+local axesPath = SvgWriter.Path();
+
+local axes = {}
+
+axes[#axes + 1] = vmath.vec2((upperBound[1] + lowerBound[1]) / 2, 0);
+axes[#axes + 1] = vmath.vec2((upperBound[1] + lowerBound[1]) / 2, lowerBound[2]);
+axes[#axes + 1] = vmath.vec2((upperBound[1] + lowerBound[1]) / 2, 0);
+axes[#axes + 1] = vmath.vec2((upperBound[1] + lowerBound[1]) / 2, upperBound[2]);
+axes[#axes + 1] = vmath.vec2(0, (upperBound[2] + lowerBound[2]) / 2);
+axes[#axes + 1] = vmath.vec2(upperBound[1], (upperBound[2] + lowerBound[2]) / 2);
+axes[#axes + 1] = vmath.vec2(0, (upperBound[2] + lowerBound[2]) / 2);
+axes[#axes + 1] = vmath.vec2(lowerBound[1], (upperBound[2] + lowerBound[2]) / 2);
+
+axes = vp:Transform(axes)
+
+--Draw coodinate axes and objects.
+local coordAxes =
+{
+	vmath.vec2(0, 0),
+	vmath.vec2(1, 0),
+	vmath.vec2(0, 1),
+}
+
+local triangle =
+{
+	vmath.vec2(0.5, 2.5),
+	vmath.vec2(2.0, -1),
+	vmath.vec2(-3, -0.5),
+}
+
+local writer = SvgWriter.SvgWriter("RotationTransform.svg", {subImages:Size().x .."px", subImages:Size().y .. "px"});
+	writer:StyleLibrary(styleLib);
+	writer:BeginDefinitions();
+		writer:BeginMarker({pointSize, pointSize}, {pointSize/2, pointSize/2}, "auto", true, nil, "m_point");
+			writer:Circle({pointSize/2, pointSize/2}, pointSize/2, {"point"});
+		writer:EndMarker();
+		writer:BeginMarker({10, 8}, {10, 4}, "auto", true, nil, "arrow");
+			writer:Path(arrowheadPath, {"fill_black", "thin"});
+		writer:EndMarker();
+		writer:BeginMarker({10, 20}, {10, 10}, "auto", true, nil, "big_arrow_y_axis");
+			writer:Path(bigArrowheadPath, {"y_axis_marker"});
+		writer:EndMarker();
+		writer:BeginMarker({10, 20}, {10, 10}, "auto", true, nil, "big_arrow_x_axis");
+			writer:Path(bigArrowheadPath, {"x_axis_marker"});
+		writer:EndMarker();
+		writer:BeginGroup(nil, "g_axes");
+			writer:Path(gridPath, {"grid"});
+			for i=1, #axes, 2 do
+				writer:Line(axes[i], axes[i+1], {"axes"});
+			end
+		writer:EndGroup();
+	writer:EndDefinitions();
+
+	--Left side.
+	writer:Use("g_axes", subImages:Offset(1, 1), subImages:SubSize());
+	
+	local origCoordAxes = subImages:Transform({1, 1}, vp:Transform(coordAxes))
+	writer:Line(origCoordAxes[1], origCoordAxes[2], {"x_axis"});
+	writer:Line(origCoordAxes[1], origCoordAxes[3], {"y_axis"});
+
+	local origTriangle = subImages:Transform({1, 1}, vp:Transform(triangle))
+	writer:Polygon(origTriangle, {"triangle"});
+
+	--Right side.
+	writer:Use("g_axes", subImages:Offset(2, 1), subImages:SubSize());
+
+	trans2:Rotate(75);
+	local newCoordAxes = subImages:Transform({2, 1}, vp:Transform(coordAxes))
+	writer:Line(newCoordAxes[1], newCoordAxes[2], {"x_axis"});
+	writer:Line(newCoordAxes[1], newCoordAxes[3], {"y_axis"});
+
+	local newTriangle = subImages:Transform({2, 1}, vp:Transform(triangle))
+	writer:Polygon(newTriangle, {"triangle"});
+	
+writer:Close();

Documents/Positioning/GenScaleTransform.lua

+require "SvgWriter"
+require "vmath"
+require "Viewport"
+require "SubImage"
+
+local subImages = SubImage.SubImage(2, 1, 300, 300, 100, 0);
+
+local coordSize = 8;
+
+local vp = Viewport.Viewport({300, 300}, {0, 0}, coordSize)
+local trans2 = Viewport.Transform2D()
+vp:SetTransform(trans2);
+
+-- Styles
+local styleLib = SvgWriter.StyleLibrary();
+local pointSize = 10;
+
+local coordAxisWidth = "2px";
+local xCoordAxisColor = "green";
+local yCoordAxisColor = "red";
+local objectColor = "#AFAFFF";
+
+styleLib:AddStyle(nil, "black",
+	SvgWriter.Style():stroke("black"));
+	
+styleLib:AddStyle(nil, "grid",
+	SvgWriter.Style():stroke("#CCC"):fill("none"):stroke_width("1px"));
+
+styleLib:AddStyle(nil, "axes",
+	SvgWriter.Style():stroke("black"):fill("none"):stroke_width("2px")
+		:marker_end(SvgWriter.uriLocalElement("arrow")));
+
+styleLib:AddStyle(nil, "point",
+	SvgWriter.Style():stroke(objectColor):fill(objectColor));
+	
+styleLib:AddStyle(nil, "triangle",
+	SvgWriter.Style():stroke(objectColor):stroke_width("2px"):fill("none")
+		:marker(SvgWriter.uriLocalElement("m_point")));
+	
+styleLib:AddStyle(nil, "x_axis",
+	SvgWriter.Style():stroke(xCoordAxisColor):stroke_width(coordAxisWidth):fill("none")
+		:marker_end(SvgWriter.uriLocalElement("big_arrow_x_axis")));
+	
+styleLib:AddStyle(nil, "y_axis",
+	SvgWriter.Style():stroke(yCoordAxisColor):stroke_width(coordAxisWidth):fill("none")
+		:marker_end(SvgWriter.uriLocalElement("big_arrow_y_axis")));
+	
+styleLib:AddStyle(nil, "x_axis_marker",
+	SvgWriter.Style():stroke(xCoordAxisColor):stroke_width(coordAxisWidth):fill("none"));
+
+styleLib:AddStyle(nil, "y_axis_marker",
+	SvgWriter.Style():stroke(yCoordAxisColor):stroke_width(coordAxisWidth):fill("none"));
+
+styleLib:AddStyle(nil, "arrow_end",
+	SvgWriter.Style():marker_end(SvgWriter.uriLocalElement("arrow")));
+
+local arrowheadPath = SvgWriter.Path();
+arrowheadPath:M{10, 4}:L{0, 0}:L{0, 8}:Z();
+
+local bigArrowheadPath = SvgWriter.Path();
+bigArrowheadPath:M{0, 0}:L{10, 10}:L{0, 20};
+
+--Generate grid.
+local upperBound, lowerBound = vp:Extents();
+
+local gridPath = SvgWriter.Path();
+
+--Vertical lines.
+for i = lowerBound[1], upperBound[1] do
+	local points =
+	{
+		vmath.vec2(i, lowerBound[2]);
+		vmath.vec2(i, upperBound[2]);
+	};
+	
+	points = vp:Transform(points)
+	gridPath:M(points[1]):V(points[2][2]);
+end
+
+--Horizontal lines.
+for i = lowerBound[2], upperBound[2] do
+	local points =
+	{
+		vmath.vec2(lowerBound[1], i);
+		vmath.vec2(upperBound[1], i);
+	};
+	
+	points = vp:Transform(points)
+	gridPath:M(points[1]):H(points[2][1]);
+end
+
+local axesPath = SvgWriter.Path();
+
+local axes = {}
+
+axes[#axes + 1] = vmath.vec2((upperBound[1] + lowerBound[1]) / 2, 0);
+axes[#axes + 1] = vmath.vec2((upperBound[1] + lowerBound[1]) / 2, lowerBound[2]);
+axes[#axes + 1] = vmath.vec2((upperBound[1] + lowerBound[1]) / 2, 0);
+axes[#axes + 1] = vmath.vec2((upperBound[1] + lowerBound[1]) / 2, upperBound[2]);
+axes[#axes + 1] = vmath.vec2(0, (upperBound[2] + lowerBound[2]) / 2);
+axes[#axes + 1] = vmath.vec2(upperBound[1], (upperBound[2] + lowerBound[2]) / 2);
+axes[#axes + 1] = vmath.vec2(0, (upperBound[2] + lowerBound[2]) / 2);
+axes[#axes + 1] = vmath.vec2(lowerBound[1], (upperBound[2] + lowerBound[2]) / 2);
+
+axes = vp:Transform(axes)
+
+--Draw coodinate axes and objects.
+local coordAxes =
+{
+	vmath.vec2(0, 0),
+	vmath.vec2(1, 0),
+	vmath.vec2(0, 1),
+}
+
+local triangle =
+{
+	vmath.vec2(0.5, 2.5),
+	vmath.vec2(2.0, -1),
+	vmath.vec2(-3, -0.5),
+}
+
+
+
+
+local writer = SvgWriter.SvgWriter("ScaleTransform.svg", {subImages:Size().x .."px", subImages:Size().y .. "px"});
+	writer:StyleLibrary(styleLib);
+	writer:BeginDefinitions();
+		writer:BeginMarker({pointSize, pointSize}, {pointSize/2, pointSize/2}, "auto", true, nil, "m_point");
+			writer:Circle({pointSize/2, pointSize/2}, pointSize/2, {"point"});
+		writer:EndMarker();
+		writer:BeginMarker({10, 8}, {10, 4}, "auto", true, nil, "arrow");
+			writer:Path(arrowheadPath, {"fill_black", "thin"});
+		writer:EndMarker();
+		writer:BeginMarker({10, 20}, {10, 10}, "auto", true, nil, "big_arrow_y_axis");
+			writer:Path(bigArrowheadPath, {"y_axis_marker"});
+		writer:EndMarker();
+		writer:BeginMarker({10, 20}, {10, 10}, "auto", true, nil, "big_arrow_x_axis");
+			writer:Path(bigArrowheadPath, {"x_axis_marker"});
+		writer:EndMarker();
+		writer:BeginGroup(nil, "g_axes");
+			writer:Path(gridPath, {"grid"});
+			for i=1, #axes, 2 do
+				writer:Line(axes[i], axes[i+1], {"axes"});
+			end
+		writer:EndGroup();
+	writer:EndDefinitions();
+
+	--Left side.
+	writer:Use("g_axes", subImages:Offset(1, 1), subImages:SubSize());
+	
+	local origCoordAxes = subImages:Transform({1, 1}, vp:Transform(coordAxes))
+	writer:Line(origCoordAxes[1], origCoordAxes[2], {"x_axis"});
+	writer:Line(origCoordAxes[1], origCoordAxes[3], {"y_axis"});
+
+	local origTriangle = subImages:Transform({1, 1}, vp:Transform(triangle))
+	writer:Polygon(origTriangle, {"triangle"});
+
+	--Right side.
+	writer:Use("g_axes", subImages:Offset(2, 1), subImages:SubSize());
+
+	trans2:Scale(vmath.vec2(0.5, 1.2));
+	local newCoordAxes = subImages:Transform({2, 1}, vp:Transform(coordAxes))
+	writer:Line(newCoordAxes[1], newCoordAxes[2], {"x_axis"});
+	writer:Line(newCoordAxes[1], newCoordAxes[3], {"y_axis"});
+
+	local newTriangle = subImages:Transform({2, 1}, vp:Transform(triangle))
+	writer:Polygon(newTriangle, {"triangle"});
+	
+writer:Close();

Documents/Positioning/GenTransOrderGeom.lua

+require "SvgWriter"
+require "vmath"
+require "Viewport"
+require "SubImage"
+
+subImageSize = 250;
+
+local subImages = SubImage.SubImage(3, 2, subImageSize, subImageSize, 50, 50);
+
+local labelOffset = vmath.vec2(-35, 135);
+
+local coordSize = 14;
+
+local vp = Viewport.Viewport({subImageSize, subImageSize}, {0, 0}, coordSize)
+local trans2 = Viewport.Transform2D()
+vp:SetTransform(trans2);
+
+local vpUpRight = Viewport.Viewport({subImageSize, subImageSize}, {0, 0}, coordSize)
+vpUpRight:SetTransform(trans2);
+
+-- Styles
+local styleLib = SvgWriter.StyleLibrary();
+local pointSize = 10;
+
+local coordAxisWidth = "2px";
+local xCoordAxisColor = "#20FF20";
+local yCoordAxisColor = "red";
+local objectColor = "#AFAFFF";
+
+styleLib:AddStyle(nil, "text",
+	SvgWriter.Style():stroke("black"):stroke_width("1px"):font_size("30px"):font_family("monospace"));
+	
+styleLib:AddStyle(nil, "grid",
+	SvgWriter.Style():stroke("#CCC"):fill("none"):stroke_width("1px"));
+
+styleLib:AddStyle(nil, "axes",
+	SvgWriter.Style():stroke("black"):fill("none"):stroke_width("2px")
+		:marker_end(SvgWriter.uriLocalElement("arrow")));
+
+styleLib:AddStyle(nil, "point",
+	SvgWriter.Style():stroke(objectColor):fill(objectColor));
+	
+styleLib:AddStyle(nil, "triangle",
+	SvgWriter.Style():stroke(objectColor):stroke_width("2px"):fill("none")
+		:marker(SvgWriter.uriLocalElement("m_point")));
+	
+styleLib:AddStyle(nil, "x_axis",
+	SvgWriter.Style():stroke(xCoordAxisColor):stroke_width(coordAxisWidth):fill("none")
+--		:marker_end(SvgWriter.uriLocalElement("big_arrow_x_axis"))
+		);
+	
+styleLib:AddStyle(nil, "y_axis",
+	SvgWriter.Style():stroke(yCoordAxisColor):stroke_width(coordAxisWidth):fill("none")
+--		:marker_end(SvgWriter.uriLocalElement("big_arrow_y_axis"))
+		);
+	
+styleLib:AddStyle(nil, "x_axis_marker",
+	SvgWriter.Style():stroke(xCoordAxisColor):stroke_width(coordAxisWidth):fill("none"));
+
+styleLib:AddStyle(nil, "y_axis_marker",
+	SvgWriter.Style():stroke(yCoordAxisColor):stroke_width(coordAxisWidth):fill("none"));
+
+styleLib:AddStyle(nil, "arrow_end",
+	SvgWriter.Style():marker_end(SvgWriter.uriLocalElement("arrow")));
+
+styleLib:AddStyle(nil, "text",
+	SvgWriter.Style():font_size("30px"):font_family("monospace") );
+
+local arrowheadPath = SvgWriter.Path();
+arrowheadPath:M{10, 4}:L{0, 0}:L{0, 8}:Z();
+
+local bigArrowheadPath = SvgWriter.Path();
+bigArrowheadPath:M{0, 0}:L{10, 10}:L{0, 20};
+
+--Generate grid.
+local upperBound, lowerBound = vp:Extents();
+
+local gridPath = SvgWriter.Path();
+
+--Vertical lines.
+for i = lowerBound[1], upperBound[1] do
+	local points =
+	{
+		vmath.vec2(i, lowerBound[2]);
+		vmath.vec2(i, upperBound[2]);
+	};
+	
+	points = vp:Transform(points)
+	gridPath:M(points[1]):V(points[2][2]);
+end
+
+--Horizontal lines.
+for i = lowerBound[2], upperBound[2] do
+	local points =
+	{
+		vmath.vec2(lowerBound[1], i);
+		vmath.vec2(upperBound[1], i);
+	};
+	
+	points = vp:Transform(points)
+	gridPath:M(points[1]):H(points[2][1]);
+end
+
+local axesPath = SvgWriter.Path();
+
+local axes = {}
+
+axes[#axes + 1] = vmath.vec2((upperBound[1] + lowerBound[1]) / 2, 0);
+axes[#axes + 1] = vmath.vec2((upperBound[1] + lowerBound[1]) / 2, lowerBound[2]);
+axes[#axes + 1] = vmath.vec2((upperBound[1] + lowerBound[1]) / 2, 0);
+axes[#axes + 1] = vmath.vec2((upperBound[1] + lowerBound[1]) / 2, upperBound[2]);
+axes[#axes + 1] = vmath.vec2(0, (upperBound[2] + lowerBound[2]) / 2);
+axes[#axes + 1] = vmath.vec2(upperBound[1], (upperBound[2] + lowerBound[2]) / 2);
+axes[#axes + 1] = vmath.vec2(0, (upperBound[2] + lowerBound[2]) / 2);
+axes[#axes + 1] = vmath.vec2(lowerBound[1], (upperBound[2] + lowerBound[2]) / 2);
+
+axes = vp:Transform(axes)
+
+--Draw coodinate axes and objects.
+local coordAxes =
+{
+	vmath.vec2(0, 0),
+	vmath.vec2(1, 0),
+	vmath.vec2(0, 1),
+}
+
+local triangle =
+{
+	vmath.vec2(0.5, 3.5),
+	vmath.vec2(1.0, -2),
+	vmath.vec2(-2.0, -3.5),
+}
+
+
+local writer = SvgWriter.SvgWriter("TransOrderGeom.svg", {subImages:Size().x .."px", subImages:Size().y .. "px"});
+	writer:StyleLibrary(styleLib);
+	writer:BeginDefinitions();
+		writer:BeginMarker({pointSize, pointSize}, {pointSize/2, pointSize/2}, "auto", true, nil, "m_point");
+			writer:Circle({pointSize/2, pointSize/2}, pointSize/2, {"point"});
+		writer:EndMarker();
+		writer:BeginMarker({10, 8}, {10, 4}, "auto", true, nil, "arrow");
+			writer:Path(arrowheadPath, {"fill_black", "thin"});
+		writer:EndMarker();
+		writer:BeginMarker({10, 20}, {10, 10}, "auto", true, nil, "big_arrow_y_axis");
+			writer:Path(bigArrowheadPath, {"y_axis_marker"});
+		writer:EndMarker();
+		writer:BeginMarker({10, 20}, {10, 10}, "auto", true, nil, "big_arrow_x_axis");
+			writer:Path(bigArrowheadPath, {"x_axis_marker"});
+		writer:EndMarker();
+		writer:BeginGroup(nil, "g_axes");
+			writer:Path(gridPath, {"grid"});
+			for i=1, #axes, 2 do
+				writer:Line(axes[i], axes[i+1], {"axes"});
+			end
+		writer:EndGroup();
+	writer:EndDefinitions();
+
+	--Left side.
+	writer:Use("g_axes", subImages:Offset(1, 1), subImages:SubSize());
+	
+	local origCoordAxes = subImages:Transform({1, 1}, vp:Transform(coordAxes))
+	writer:Line(origCoordAxes[1], origCoordAxes[2], {"x_axis"});
+	writer:Line(origCoordAxes[1], origCoordAxes[3], {"y_axis"});
+
+	local origTriangle = subImages:Transform({1, 1}, vp:Transform(triangle))
+	writer:Polygon(origTriangle, {"triangle"});
+
+	--Middle side.
+	writer:Use("g_axes", subImages:Offset(2, 1), subImages:SubSize());
+
+	trans2:Translate(vmath.vec2(2, 1));
+	local newCoordAxes = subImages:Transform({2, 1}, vpUpRight:Transform(coordAxes))
+	writer:Line(newCoordAxes[1], newCoordAxes[2], {"x_axis"});
+	writer:Line(newCoordAxes[1], newCoordAxes[3], {"y_axis"});
+
+	local newTriangle = subImages:Transform({2, 1}, vpUpRight:Transform(triangle))
+	writer:Polygon(newTriangle, {"triangle"});
+	
+	--Right side
+	writer:Use("g_axes", subImages:Offset(3, 1), subImages:SubSize());
+
+	trans2:Identity();
+	trans2:Scale(vmath.vec2(2, 0.5));
+	trans2:Translate(vmath.vec2(2, 1));
+	local newCoordAxes = subImages:Transform({3, 1}, vpUpRight:Transform(coordAxes))
+	writer:Line(newCoordAxes[1], newCoordAxes[2], {"x_axis"});
+	writer:Line(newCoordAxes[1], newCoordAxes[3], {"y_axis"});
+
+	local newTriangle = subImages:Transform({3, 1}, vpUpRight:Transform(triangle))
+	writer:Polygon(newTriangle, {"triangle"});
+
+	trans2:Identity();
+
+	--Left side.
+	writer:Use("g_axes", subImages:Offset(1, 2), subImages:SubSize());
+	
+	local origCoordAxes = subImages:Transform({1, 2}, vp:Transform(coordAxes))
+	writer:Line(origCoordAxes[1], origCoordAxes[2], {"x_axis"});
+	writer:Line(origCoordAxes[1], origCoordAxes[3], {"y_axis"});
+
+	local origTriangle = subImages:Transform({1, 2}, vp:Transform(triangle))
+	writer:Polygon(origTriangle, {"triangle"});
+
+	--Middle side.
+	writer:Use("g_axes", subImages:Offset(2, 2), subImages:SubSize());
+
+	trans2:Scale(vmath.vec2(2, 0.5));
+	local newCoordAxes = subImages:Transform({2, 2}, vpUpRight:Transform(coordAxes))
+	writer:Line(newCoordAxes[1], newCoordAxes[2], {"x_axis"});
+	writer:Line(newCoordAxes[1], newCoordAxes[3], {"y_axis"});
+
+	local newTriangle = subImages:Transform({2, 2}, vpUpRight:Transform(triangle))
+	writer:Polygon(newTriangle, {"triangle"});
+	
+	--Right side
+	writer:Use("g_axes", subImages:Offset(3, 2), subImages:SubSize());
+
+	trans2:Identity();
+	trans2:Translate(vmath.vec2(2, 1));
+	trans2:Scale(vmath.vec2(2, 0.5));
+	local newCoordAxes = subImages:Transform({3, 2}, vpUpRight:Transform(coordAxes))
+	writer:Line(newCoordAxes[1], newCoordAxes[2], {"x_axis"});
+	writer:Line(newCoordAxes[1], newCoordAxes[3], {"y_axis"});
+
+	local newTriangle = subImages:Transform({3, 2}, vpUpRight:Transform(triangle))
+	writer:Polygon(newTriangle, {"triangle"});
+
+	--Labels
+	writer:Text("T", labelOffset + subImages:Offset(2, 1), {"text"});
+	writer:Text("S", labelOffset + subImages:Offset(3, 1), {"text"});
+	writer:Text("S", labelOffset + subImages:Offset(2, 2), {"text"});
+	writer:Text("T", labelOffset + subImages:Offset(3, 2), {"text"});
+writer:Close();

Documents/Positioning/GenTranslationTransform.lua

+require "SvgWriter"
+require "vmath"
+require "Viewport"
+require "SubImage"
+
+local subImages = SubImage.SubImage(2, 1, 300, 300, 100, 0);
+
+local coordSize = 8;
+
+local vp = Viewport.Viewport({300, 300}, {0, 0}, coordSize)
+local trans2 = Viewport.Transform2D()
+vp:SetTransform(trans2);
+
+-- Styles
+local styleLib = SvgWriter.StyleLibrary();
+local pointSize = 10;
+
+local coordAxisWidth = "2px";
+local xCoordAxisColor = "green";
+local yCoordAxisColor = "red";
+local objectColor = "#AFAFFF";
+
+styleLib:AddStyle(nil, "black",
+	SvgWriter.Style():stroke("black"));
+	
+styleLib:AddStyle(nil, "grid",
+	SvgWriter.Style():stroke("#CCC"):fill("none"):stroke_width("1px"));
+
+styleLib:AddStyle(nil, "axes",
+	SvgWriter.Style():stroke("black"):fill("none"):stroke_width("2px")
+		:marker_end(SvgWriter.uriLocalElement("arrow")));
+
+styleLib:AddStyle(nil, "point",
+	SvgWriter.Style():stroke(objectColor):fill(objectColor));
+	
+styleLib:AddStyle(nil, "triangle",
+	SvgWriter.Style():stroke(objectColor):stroke_width("2px"):fill("none")
+		:marker(SvgWriter.uriLocalElement("m_point")));
+	
+styleLib:AddStyle(nil, "x_axis",
+	SvgWriter.Style():stroke(xCoordAxisColor):stroke_width(coordAxisWidth):fill("none")
+		:marker_end(SvgWriter.uriLocalElement("big_arrow_x_axis")));
+	
+styleLib:AddStyle(nil, "y_axis",
+	SvgWriter.Style():stroke(yCoordAxisColor):stroke_width(coordAxisWidth):fill("none")
+		:marker_end(SvgWriter.uriLocalElement("big_arrow_y_axis")));
+	
+styleLib:AddStyle(nil, "x_axis_marker",
+	SvgWriter.Style():stroke(xCoordAxisColor):stroke_width(coordAxisWidth):fill("none"));
+
+styleLib:AddStyle(nil, "y_axis_marker",
+	SvgWriter.Style():stroke(yCoordAxisColor):stroke_width(coordAxisWidth):fill("none"));
+
+styleLib:AddStyle(nil, "arrow_end",
+	SvgWriter.Style():marker_end(SvgWriter.uriLocalElement("arrow")));
+
+local arrowheadPath = SvgWriter.Path();
+arrowheadPath:M{10, 4}:L{0, 0}:L{0, 8}:Z();
+
+local bigArrowheadPath = SvgWriter.Path();
+bigArrowheadPath:M{0, 0}:L{10, 10}:L{0, 20};
+
+--Generate grid.
+local upperBound, lowerBound = vp:Extents();
+
+local gridPath = SvgWriter.Path();
+
+--Vertical lines.
+for i = lowerBound[1], upperBound[1] do
+	local points =
+	{
+		vmath.vec2(i, lowerBound[2]);
+		vmath.vec2(i, upperBound[2]);
+	};
+	
+	points = vp:Transform(points)
+	gridPath:M(points[1]):V(points[2][2]);
+end
+
+--Horizontal lines.
+for i = lowerBound[2], upperBound[2] do
+	local points =
+	{
+		vmath.vec2(lowerBound[1], i);
+		vmath.vec2(upperBound[1], i);
+	};
+	
+	points = vp:Transform(points)
+	gridPath:M(points[1]):H(points[2][1]);
+end
+
+local axesPath = SvgWriter.Path();
+
+local axes = {}
+
+axes[#axes + 1] = vmath.vec2((upperBound[1] + lowerBound[1]) / 2, 0);
+axes[#axes + 1] = vmath.vec2((upperBound[1] + lowerBound[1]) / 2, lowerBound[2]);
+axes[#axes + 1] = vmath.vec2((upperBound[1] + lowerBound[1]) / 2, 0);
+axes[#axes + 1] = vmath.vec2((upperBound[1] + lowerBound[1]) / 2, upperBound[2]);
+axes[#axes + 1] = vmath.vec2(0, (upperBound[2] + lowerBound[2]) / 2);
+axes[#axes + 1] = vmath.vec2(upperBound[1], (upperBound[2] + lowerBound[2]) / 2);
+axes[#axes + 1] = vmath.vec2(0, (upperBound[2] + lowerBound[2]) / 2);
+axes[#axes + 1] = vmath.vec2(lowerBound[1], (upperBound[2] + lowerBound[2]) / 2);
+
+axes = vp:Transform(axes)
+
+--Draw coodinate axes and objects.
+local coordAxes =
+{
+	vmath.vec2(0, 0),
+	vmath.vec2(1, 0),
+	vmath.vec2(0, 1),
+}
+
+local triangle =
+{
+	vmath.vec2(0.5, 2.5),
+	vmath.vec2(2.0, -1),
+	vmath.vec2(-3, -0.5),
+}
+
+
+
+
+local writer = SvgWriter.SvgWriter("TranslationTransform.svg", {subImages:Size().x .."px", subImages:Size().y .. "px"});
+	writer:StyleLibrary(styleLib);
+	writer:BeginDefinitions();
+		writer:BeginMarker({pointSize, pointSize}, {pointSize/2, pointSize/2}, "auto", true, nil, "m_point");
+			writer:Circle({pointSize/2, pointSize/2}, pointSize/2, {"point"});
+		writer:EndMarker();
+		writer:BeginMarker({10, 8}, {10, 4}, "auto", true, nil, "arrow");
+			writer:Path(arrowheadPath, {"fill_black", "thin"});
+		writer:EndMarker();
+		writer:BeginMarker({10, 20}, {10, 10}, "auto", true, nil, "big_arrow_y_axis");
+			writer:Path(bigArrowheadPath, {"y_axis_marker"});
+		writer:EndMarker();
+		writer:BeginMarker({10, 20}, {10, 10}, "auto", true, nil, "big_arrow_x_axis");
+			writer:Path(bigArrowheadPath, {"x_axis_marker"});
+		writer:EndMarker();
+		writer:BeginGroup(nil, "g_axes");
+			writer:Path(gridPath, {"grid"});
+			for i=1, #axes, 2 do
+				writer:Line(axes[i], axes[i+1], {"axes"});
+			end
+		writer:EndGroup();
+	writer:EndDefinitions();
+
+	--Left side.
+	writer:Use("g_axes", subImages:Offset(1, 1), subImages:SubSize());
+	
+	local origCoordAxes = subImages:Transform({1, 1}, vp:Transform(coordAxes))
+	writer:Line(origCoordAxes[1], origCoordAxes[2], {"x_axis"});
+	writer:Line(origCoordAxes[1], origCoordAxes[3], {"y_axis"});
+
+	local origTriangle = subImages:Transform({1, 1}, vp:Transform(triangle))
+	writer:Polygon(origTriangle, {"triangle"});
+
+	--Right side.
+	writer:Use("g_axes", subImages:Offset(2, 1), subImages:SubSize());
+
+	trans2:Translate(vmath.vec2(1, -1.5));
+	local newCoordAxes = subImages:Transform({2, 1}, vp:Transform(coordAxes))
+	writer:Line(newCoordAxes[1], newCoordAxes[2], {"x_axis"});
+	writer:Line(newCoordAxes[1], newCoordAxes[3], {"y_axis"});
+
+	local newTriangle = subImages:Transform({2, 1}, vp:Transform(triangle))
+	writer:Polygon(newTriangle, {"triangle"});
+	
+writer:Close();

Documents/Positioning/GenWindingOrder.lua

 
 
 -- The SVG itself.
-local writer = SvgWriter.SvgWriter("testSubImage.svg", {subImages:Size().x .."px", subImages:Size().y .. "px"});
+local writer = SvgWriter.SvgWriter("WindingOrder.svg", {subImages:Size().x .."px", subImages:Size().y .. "px"});
 	writer:StyleLibrary(styleLib);
 	writer:BeginDefinitions();
 		writer:BeginMarker({pointSize, pointSize}, {pointSize/2, pointSize/2}, "auto", true, nil, "point");
Add a comment to this file

Documents/Positioning/RotationTransform.svg

Added
New image
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" height="300px" width="700px" >
+	<style type="text/css" ><![CDATA[.triangle
+{
+	marker: url(#m_point);
+	stroke: #AFAFFF;
+	stroke-width: 2px;
+	fill: none;
+}
+
+.black
+{
+	stroke: black;
+}
+
+.arrow_end
+{
+	marker-end: url(#arrow);
+}
+
+.y_axis_marker
+{
+	stroke: red;
+	stroke-width: 2px;
+	fill: none;
+}
+
+.point
+{
+	fill: #AFAFFF;
+	stroke: #AFAFFF;
+}
+
+.x_axis
+{
+	marker-end: url(#big_arrow_x_axis);
+	stroke: green;
+	stroke-width: 2px;
+	fill: none;
+}
+
+.x_axis_marker
+{
+	stroke: green;
+	stroke-width: 2px;
+	fill: none;
+}
+
+.y_axis
+{
+	marker-end: url(#big_arrow_y_axis);
+	stroke: red;
+	stroke-width: 2px;
+	fill: none;
+}
+
+.grid
+{
+	stroke: #CCC;
+	stroke-width: 1px;
+	fill: none;
+}
+
+.axes
+{
+	marker-end: url(#arrow);
+	stroke: black;
+	stroke-width: 2px;
+	fill: none;
+}]]></style>
+	<defs >
+		<marker markerWidth="10" markerHeight="10" refX="5" refY="5" markerUnits="userSpaceOnUse" orient="auto" id="m_point" >
+			<circle r="5" cy="5" cx="5" class="point" />
+		</marker>
+		<marker markerWidth="10" markerHeight="8" refX="10" refY="4" markerUnits="userSpaceOnUse" orient="auto" id="arrow" >
+			<path d="M 10 4 L 0 0 L 0 8 Z" class="fill_black thin" />
+		</marker>
+		<marker markerWidth="10" markerHeight="20" refX="10" refY="10" markerUnits="userSpaceOnUse" orient="auto" id="big_arrow_y_axis" >
+			<path d="M 0 0 L 10 10 L 0 20" class="y_axis_marker" />
+		</marker>
+		<marker markerWidth="10" markerHeight="20" refX="10" refY="10" markerUnits="userSpaceOnUse" orient="auto" id="big_arrow_x_axis" >
+			<path d="M 0 0 L 10 10 L 0 20" class="x_axis_marker" />
+		</marker>
+		<g id="g_axes" >
+			<path d="M 0 300 V 0 M 37.5 300 V 0 M 75 300 V 0 M 112.5 300 V 0 M 150 300 V 0 M 187.5 300 V 0 M 225 300 V 0 M 262.5 300 V 0 M 300 300 V 0 M 0 300 H 300 M 0 262.5 H 300 M 0 225 H 300 M 0 187.5 H 300 M 0 150 H 300 M 0 112.5 H 300 M 0 75 H 300 M 0 37.5 H 300 M 0 0 H 300" class="grid" />
+			<line x2="150" y2="300" y1="150" x1="150" class="axes" />
+			<line x2="150" y2="0" y1="150" x1="150" class="axes" />
+			<line x2="300" y2="150" y1="150" x1="150" class="axes" />
+			<line x2="0" y2="150" y1="150" x1="150" class="axes" />
+		</g>
+	</defs>
+	<use xlink:href="#g_axes" y="0" x="0" height="300" width="300" />
+	<line x2="187.5" y2="150" y1="150" x1="150" class="x_axis" />
+	<line x2="150" y2="112.5" y1="150" x1="150" class="y_axis" />
+	<polygon points="168.75,56.25 225,187.5 37.5,168.75" class="triangle" />
+	<use xlink:href="#g_axes" y="0" x="400" height="300" width="300" />
+	<line x2="559.70571419134" y2="186.22221848584" y1="150" x1="550" class="x_axis" />
+	<line x2="586.22221848584" y2="140.29428580866" y1="150" x1="550" class="y_axis" />
+	<polygon points="645.40840331027,143.84682376456 533.18920989685,232.15015116302 502.77174818305,46.186201638152" class="triangle" />
+</svg>
Add a comment to this file

Documents/Positioning/ScaleTransform.svg

Added
New image
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" height="300px" width="700px" >
+	<style type="text/css" ><![CDATA[.arrow_end
+{
+	marker-end: url(#arrow);
+}
+
+.grid
+{
+	stroke: #CCC;
+	stroke-width: 1px;
+	fill: none;
+}
+
+.y_axis
+{
+	marker-end: url(#big_arrow_y_axis);
+	stroke: red;
+	stroke-width: 2px;
+	fill: none;
+}
+
+.black
+{
+	stroke: black;
+}
+
+.x_axis_marker
+{
+	stroke: green;
+	stroke-width: 2px;
+	fill: none;
+}
+
+.point
+{
+	fill: #AFAFFF;
+	stroke: #AFAFFF;
+}
+
+.y_axis_marker
+{
+	stroke: red;
+	stroke-width: 2px;
+	fill: none;
+}
+
+.triangle
+{
+	marker: url(#m_point);
+	stroke: #AFAFFF;
+	stroke-width: 2px;
+	fill: none;
+}
+
+.axes
+{
+	marker-end: url(#arrow);
+	stroke: black;
+	stroke-width: 2px;
+	fill: none;
+}
+
+.x_axis
+{
+	marker-end: url(#big_arrow_x_axis);
+	stroke: green;
+	stroke-width: 2px;
+	fill: none;
+}]]></style>
+	<defs >
+		<marker markerWidth="10" markerHeight="10" refX="5" refY="5" markerUnits="userSpaceOnUse" orient="auto" id="m_point" >
+			<circle r="5" cy="5" cx="5" class="point" />
+		</marker>
+		<marker markerWidth="10" markerHeight="8" refX="10" refY="4" markerUnits="userSpaceOnUse" orient="auto" id="arrow" >
+			<path d="M 10 4 L 0 0 L 0 8 Z" class="fill_black thin" />
+		</marker>
+		<marker markerWidth="10" markerHeight="20" refX="10" refY="10" markerUnits="userSpaceOnUse" orient="auto" id="big_arrow_y_axis" >
+			<path d="M 0 0 L 10 10 L 0 20" class="y_axis_marker" />
+		</marker>
+		<marker markerWidth="10" markerHeight="20" refX="10" refY="10" markerUnits="userSpaceOnUse" orient="auto" id="big_arrow_x_axis" >
+			<path d="M 0 0 L 10 10 L 0 20" class="x_axis_marker" />
+		</marker>
+		<g id="g_axes" >
+			<path d="M 0 300 V 0 M 37.5 300 V 0 M 75 300 V 0 M 112.5 300 V 0 M 150 300 V 0 M 187.5 300 V 0 M 225 300 V 0 M 262.5 300 V 0 M 300 300 V 0 M 0 300 H 300 M 0 262.5 H 300 M 0 225 H 300 M 0 187.5 H 300 M 0 150 H 300 M 0 112.5 H 300 M 0 75 H 300 M 0 37.5 H 300 M 0 0 H 300" class="grid" />
+			<line x2="150" y2="300" y1="150" x1="150" class="axes" />
+			<line x2="150" y2="0" y1="150" x1="150" class="axes" />
+			<line x2="300" y2="150" y1="150" x1="150" class="axes" />
+			<line x2="0" y2="150" y1="150" x1="150" class="axes" />
+		</g>
+	</defs>
+	<use xlink:href="#g_axes" y="0" x="0" height="300" width="300" />
+	<line x2="187.5" y2="150" y1="150" x1="150" class="x_axis" />
+	<line x2="150" y2="112.5" y1="150" x1="150" class="y_axis" />
+	<polygon points="168.75,56.25 225,187.5 37.5,168.75" class="triangle" />
+	<use xlink:href="#g_axes" y="0" x="400" height="300" width="300" />
+	<line x2="568.75" y2="150" y1="150" x1="550" class="x_axis" />
+	<line x2="550" y2="105" y1="150" x1="550" class="y_axis" />
+	<polygon points="559.375,37.5 587.5,195 493.75,172.5" class="triangle" />
+</svg>
Add a comment to this file

Documents/Positioning/TransOrderGeom.svg

Added
New image
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" height="550px" width="850px" >
+	<style type="text/css" ><![CDATA[.triangle
+{
+	marker: url(#m_point);
+	stroke: #AFAFFF;
+	stroke-width: 2px;
+	fill: none;
+}
+
+.axes
+{
+	marker-end: url(#arrow);
+	stroke: black;
+	stroke-width: 2px;
+	fill: none;
+}
+
+.text
+{
+	font-size: 30px;
+	font-family: monospace;
+}
+
+.arrow_end
+{
+	marker-end: url(#arrow);
+}
+
+.x_axis_marker
+{
+	stroke: #20FF20;
+	stroke-width: 2px;
+	fill: none;
+}
+
+.y_axis_marker
+{
+	stroke: red;
+	stroke-width: 2px;
+	fill: none;
+}
+
+.point
+{
+	fill: #AFAFFF;
+	stroke: #AFAFFF;
+}
+
+.text
+{
+	font-size: 30px;
+	stroke: black;
+	font-family: monospace;
+	stroke-width: 1px;
+}
+
+.grid
+{
+	stroke: #CCC;
+	stroke-width: 1px;
+	fill: none;
+}
+
+.x_axis
+{
+	stroke: #20FF20;
+	stroke-width: 2px;
+	fill: none;
+}
+
+.y_axis
+{
+	stroke: red;
+	stroke-width: 2px;
+	fill: none;
+}]]></style>
+	<defs >
+		<marker markerWidth="10" markerHeight="10" refX="5" refY="5" markerUnits="userSpaceOnUse" orient="auto" id="m_point" >
+			<circle r="5" cy="5" cx="5" class="point" />
+		</marker>
+		<marker markerWidth="10" markerHeight="8" refX="10" refY="4" markerUnits="userSpaceOnUse" orient="auto" id="arrow" >
+			<path d="M 10 4 L 0 0 L 0 8 Z" class="fill_black thin" />
+		</marker>
+		<marker markerWidth="10" markerHeight="20" refX="10" refY="10" markerUnits="userSpaceOnUse" orient="auto" id="big_arrow_y_axis" >
+			<path d="M 0 0 L 10 10 L 0 20" class="y_axis_marker" />
+		</marker>
+		<marker markerWidth="10" markerHeight="20" refX="10" refY="10" markerUnits="userSpaceOnUse" orient="auto" id="big_arrow_x_axis" >
+			<path d="M 0 0 L 10 10 L 0 20" class="x_axis_marker" />
+		</marker>
+		<g id="g_axes" >
+			<path d="M 0 250 V 0 M 17.857142857143 250 V 0 M 35.714285714286 250 V 0 M 53.571428571429 250 V 0 M 71.428571428571 250 V 0 M 89.285714285714 250 V 0 M 107.14285714286 250 V 0 M 125 250 V 0 M 142.85714285714 250 V 0 M 160.71428571429 250 V 0 M 178.57142857143 250 V 0 M 196.42857142857 250 V 0 M 214.28571428571 250 V 0 M 232.14285714286 250 V 0 M 250 250 V 0 M 0 250 H 250 M 0 232.14285714286 H 250 M 0 214.28571428571 H 250 M 0 196.42857142857 H 250 M 0 178.57142857143 H 250 M 0 160.71428571429 H 250 M 0 142.85714285714 H 250 M 0 125 H 250 M 0 107.14285714286 H 250 M 0 89.285714285714 H 250 M 0 71.428571428571 H 250 M 0 53.571428571429 H 250 M 0 35.714285714286 H 250 M 0 17.857142857143 H 250 M 0 0 H 250" class="grid" />
+			<line x2="125" y2="250" y1="125" x1="125" class="axes" />
+			<line x2="125" y2="0" y1="125" x1="125" class="axes" />
+			<line x2="250" y2="125" y1="125" x1="125" class="axes" />
+			<line x2="0" y2="125" y1="125" x1="125" class="axes" />
+		</g>
+	</defs>
+	<use xlink:href="#g_axes" y="0" x="0" height="250" width="250" />
+	<line x2="142.85714285714" y2="125" y1="125" x1="125" class="x_axis" />
+	<line x2="125" y2="107.14285714286" y1="125" x1="125" class="y_axis" />
+	<polygon points="133.92857142857,62.5 142.85714285714,160.71428571429 89.285714285714,187.5" class="triangle" />
+	<use xlink:href="#g_axes" y="0" x="300" height="250" width="250" />
+	<line x2="478.57142857143" y2="107.14285714286" y1="107.14285714286" x1="460.71428571429" class="x_axis" />
+	<line x2="460.71428571429" y2="89.285714285714" y1="107.14285714286" x1="460.71428571429" class="y_axis" />
+	<polygon points="469.64285714286,44.642857142857 478.57142857143,142.85714285714 425,169.64285714286" class="triangle" />
+	<use xlink:href="#g_axes" y="0" x="600" height="250" width="250" />
+	<line x2="832.14285714286" y2="116.07142857143" y1="116.07142857143" x1="796.42857142857" class="x_axis" />
+	<line x2="796.42857142857" y2="107.14285714286" y1="116.07142857143" x1="796.42857142857" class="y_axis" />
+	<polygon points="814.28571428571,84.821428571429 832.14285714286,133.92857142857 725,147.32142857143" class="triangle" />
+	<use xlink:href="#g_axes" y="300" x="0" height="250" width="250" />
+	<line x2="142.85714285714" y2="425" y1="425" x1="125" class="x_axis" />
+	<line x2="125" y2="407.14285714286" y1="425" x1="125" class="y_axis" />
+	<polygon points="133.92857142857,362.5 142.85714285714,460.71428571429 89.285714285714,487.5" class="triangle" />
+	<use xlink:href="#g_axes" y="300" x="300" height="250" width="250" />
+	<line x2="460.71428571429" y2="425" y1="425" x1="425" class="x_axis" />
+	<line x2="425" y2="416.07142857143" y1="425" x1="425" class="y_axis" />
+	<polygon points="442.85714285714,393.75 460.71428571429,442.85714285714 353.57142857143,456.25" class="triangle" />
+	<use xlink:href="#g_axes" y="300" x="600" height="250" width="250" />
+	<line x2="796.42857142857" y2="407.14285714286" y1="407.14285714286" x1="760.71428571429" class="x_axis" />
+	<line x2="760.71428571429" y2="398.21428571429" y1="407.14285714286" x1="760.71428571429" class="y_axis" />
+	<polygon points="778.57142857143,375.89285714286 796.42857142857,425 689.28571428571,438.39285714286" class="triangle" />
+	<text y="135" x="265" class="text" >T</text>
+	<text y="135" x="565" class="text" >S</text>
+	<text y="435" x="265" class="text" >S</text>
+	<text y="435" x="565" class="text" >T</text>
+</svg>
Add a comment to this file

Documents/Positioning/TranslationTransform.svg

Added
New image
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
+
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" height="300px" width="700px" >
+	<style type="text/css" ><![CDATA[.black
+{
+	stroke: black;
+}
+
+.triangle
+{
+	marker: url(#m_point);
+	stroke: #AFAFFF;
+	stroke-width: 2px;
+	fill: none;
+}
+
+.axes
+{
+	marker-end: url(#arrow);
+	stroke: black;
+	stroke-width: 2px;
+	fill: none;
+}
+
+.arrow_end
+{
+	marker-end: url(#arrow);
+}
+
+.y_axis_marker
+{
+	stroke: red;
+	stroke-width: 2px;
+	fill: none;
+}
+
+.point
+{
+	fill: #AFAFFF;
+	stroke: #AFAFFF;
+}
+
+.x_axis_marker
+{
+	stroke: green;
+	stroke-width: 2px;
+	fill: none;
+}
+
+.grid
+{
+	stroke: #CCC;
+	stroke-width: 1px;
+	fill: none;
+}
+
+.x_axis
+{
+	marker-end: url(#big_arrow_x_axis);
+	stroke: green;
+	stroke-width: 2px;
+	fill: none;
+}
+
+.y_axis
+{
+	marker-end: url(#big_arrow_y_axis);
+	stroke: red;
+	stroke-width: 2px;
+	fill: none;
+}]]></style>
+	<defs >
+		<marker markerWidth="10" markerHeight="10" refX="5" refY="5" markerUnits="userSpaceOnUse" orient="auto" id="m_point" >
+			<circle r="5" cy="5" cx="5" class="point" />
+		</marker>
+		<marker markerWidth="10" markerHeight="8" refX="10" refY="4" markerUnits="userSpaceOnUse" orient="auto" id="arrow" >
+			<path d="M 10 4 L 0 0 L 0 8 Z" class="fill_black thin" />
+		</marker>
+		<marker markerWidth="10" markerHeight="20" refX="10" refY="10" markerUnits="userSpaceOnUse" orient="auto" id="big_arrow_y_axis" >
+			<path d="M 0 0 L 10 10 L 0 20" class="y_axis_marker" />
+		</marker>
+		<marker markerWidth="10" markerHeight="20" refX="10" refY="10" markerUnits="userSpaceOnUse" orient="auto" id="big_arrow_x_axis" >
+			<path d="M 0 0 L 10 10 L 0 20" class="x_axis_marker" />
+		</marker>
+		<g id="g_axes" >
+			<path d="M 0 300 V 0 M 37.5 300 V 0 M 75 300 V 0 M 112.5 300 V 0 M 150 300 V 0 M 187.5 300 V 0 M 225 300 V 0 M 262.5 300 V 0 M 300 300 V 0 M 0 300 H 300 M 0 262.5 H 300 M 0 225 H 300 M 0 187.5 H 300 M 0 150 H 300 M 0 112.5 H 300 M 0 75 H 300 M 0 37.5 H 300 M 0 0 H 300" class="grid" />
+			<line x2="150" y2="300" y1="150" x1="150" class="axes" />
+			<line x2="150" y2="0" y1="150" x1="150" class="axes" />
+			<line x2="300" y2="150" y1="150" x1="150" class="axes" />
+			<line x2="0" y2="150" y1="150" x1="150" class="axes" />
+		</g>
+	</defs>
+	<use xlink:href="#g_axes" y="0" x="0" height="300" width="300" />
+	<line x2="187.5" y2="150" y1="150" x1="150" class="x_axis" />
+	<line x2="150" y2="112.5" y1="150" x1="150" class="y_axis" />
+	<polygon points="168.75,56.25 225,187.5 37.5,168.75" class="triangle" />
+	<use xlink:href="#g_axes" y="0" x="400" height="300" width="300" />
+	<line x2="625" y2="206.25" y1="206.25" x1="587.5" class="x_axis" />
+	<line x2="587.5" y2="168.75" y1="206.25" x1="587.5" class="y_axis" />
+	<polygon points="606.25,112.5 662.5,243.75 475,225" class="triangle" />
+</svg>

Documents/Positioning/Tutorial 06.xml

                 Remember: a matrix, even a translation matrix, defines a full-fledged coordinate
                 system.</para>
             <para>So S now acts on the T-space position of the vertices. T-space has an origin,
-                defined by the matrix T. A scaling transformation matrix performs scaling based on
-                the origin point in the space of the vertices being scaled. So the scaling matrix S
-                will scale the points away from the origin point in T-space. Since what you
-                (probably) actually wanted was to scale the points away from the origin point in
-                    <emphasis>model space</emphasis>, S needs to come first.</para>
+                which in T-space is (0, 0, 0), but in model space is the translation part of the
+                matrix T. A scaling transformation matrix performs scaling based on the origin point
+                in the space of the vertices being scaled. So the scaling matrix S will scale the
+                points away from the origin point in T-space. Since what you (probably) actually
+                wanted was to scale the points away from the origin point in <emphasis>model
+                    space</emphasis>, S needs to come first.</para>
             <para>Rotation (orientation) matrices have the same issue. The orientation is always
                 local to the origin in the current space of the positions. So a rotation matrix must
                 happen before the translation matrix. Scales generally should happen before
                 if it is a uniform scale, but a non-uniform scale will be problematic.</para>
             <para>There are reasons to put a translation matrix first. If the model-space origin is
                 not the point that you wish to rotate or scale around, then you will need to perform
-                the translation first, then apply a scale or rotation. Doing this multiple times can
-                allow you to scale and rotate about two completely different points. However, this
-                gets progressively more difficult, as each new translation needs to be based on the
-                space of the rotated or scaled points.</para>
+                a translation first, so that the vertices are in the space you want to rotate from,
+                then apply a scale or rotation. Doing this multiple times can allow you to scale and
+                rotate about two completely different points.</para>
         </section>
         <section>
             <title>Transformation Spaces</title>
             orientation, you apply a transformation to this matrix, storing the result as the new
             current orientation.</para>
         <para>This means that every yaw, pitch, and roll applied to the current orientation will be
-            relative to that current orientation.</para>
+            relative to that current orientation. Which is usually exactly what you want. If the
+            user applies a positive yaw, you want that yaw to rotate them relative to where they are
+            current pointing.</para>
         <para>A downside of this approach, besides the size penalty of having to store a 4x4 matrix
             rather than 3 floating-point angles, is that floating-point math can lead to errors. If
             you keep accumulating successive transformations of an object, once every 1/30th of a
             accumulating. Eventually, the orientation stops being a pure rotation and starts
             incorporating scale and skewing characteristics.</para>
         <para>The solution here is to re-orthonormalize the matrix after applying each transform. A
-            transform (space) is said to be <glossterm>orthonormal</glossterm> if the axis vectors
+            transform (space) is said to be <glossterm>orthonormal</glossterm> if the basis vectors
             are of unit length (no scale) and each axis is perpendicular to all of the
             others.</para>
-        <para>Unfortunately, re-orthonormalize a matrix is not a simple operation. You could try to
-            normalize each of the axis vectors with typical vector normalization, but that wouldn't
-            ensure that the matrix was orthonormal. It would remove scaling, but the axes wouldn't
-            be guaranteed to be perpendicular.</para>
+        <para>Unfortunately, re-orthonormalizing a matrix is not a simple operation. You could try
+            to normalize each of the axis vectors with typical vector normalization, but that
+            wouldn't ensure that the matrix was orthonormal. It would remove scaling, but the axes
+            wouldn't be guaranteed to be perpendicular.</para>
         <para>The proper solution is to use <link
                 xlink:href="http://en.wikipedia.org/wiki/Quaternions_and_spatial_rotation">unit
                 quaternions</link> to store orientations, which can be orthonormalized much more

Documents/Tools/SubImage.lua

 
 	offset.x = (self.subImageSize.x + self.spacing.x) * x;
 	offset.y = (self.subImageSize.y + self.spacing.y) * y;
-	
+
 	return offset;
 end
 
 
 --Points must be in pixel coordinates, relative to the upper-left.
 function ClassMembers:Transform(image, points)
+	local offset = self:Offset(image[1], image[2]);
 	if(vmath.vtype(points) == "table") then
 		local ret = {};
-		local offset = self:Offset(image.x, image.y);
 		for i, realPoint in ipairs(points) do
-			ret[i] = vmath.vec2(points) + offset;
+			ret[i] = vmath.vec2(realPoint) + offset;
 		end
 		return ret;
 	end
 	
-	return vmath.vec2(points) + self:Offset(image.x, image.y);
+	return vmath.vec2(points) + offset;
 end
 
 

Documents/Tools/Viewport.lua

 
 
 --2D Viewport.
-local View2D = {}
+local View = {}
 
-function View2D:Size()
+function View:Size()
 	return self.pixelSize;
 end
 
 --Takes points in viewport space, returns points in pixel space.
-function View2D:Transform(points)
+--Applies the current transform
+function View:Transform(points)
 	if(vmath.vtype(points) == "table") then
 		local ret = {};
 		for i, realPoint in ipairs(points) do
 		return ret;
 	end
 	
-	local point = vmath.vec2(points);
-	if(self.transform) then point = self.transform:Matrix():Transform(point) end;
+	local point = points;
+	if(self.transform) then
+		point = self.transform:Matrix():Transform(point)
+	end;
 	
+	point = vmath.vec2(point);
+	point = point - self.vpOrigin;
 	point = point / self.vpSize;
 	point = point * vmath.vec2(1, -1);
 	point = point * self.pixelSize;
-	point = point + self.pxOrigin;
+	point = point + self.pxCenter;
 	
 	return point;
 end
 
-function View2D:SetTransform(transform)
+--Takes points in viewport space, returns points in pixel space.
+--Does not apply the current transform
+function View:ViewportTransform(points)
+	local transform = self.transform;
+	self.transform = nil;
+	local ret = self:Transform(points);
+	self.transform = transform;
+	return ret;
+end
+
+function View:SetTransform(transform)
 	self.transform = transform;
 end
 
-
--- 3D Viewport
-local View3D = {}
-
-function View3D:Size()
-	return self.pixelSize;
+--Returns the top-right and bottom-left corners of the viewport.
+function View:Extents()
+	local halfSize = self.vpSize / 2;
+	local upperBound = self.vpOrigin + halfSize;
+	local lowerBound = self.vpOrigin - halfSize;
+	return upperBound, lowerBound;
 end
 
---Takes points in 3D viewport space, returns points in 2D pixel space.
-function View3D:Transform(points)
-	if(vmath.vtype(points) == "table") then
-		local ret = {};
-		for i, realPoint in ipairs(points) do
-			ret[i] = self:Transform(realPoint);
-		end
-		return ret;
-	end
+function Viewport(pixelSize, vpOrigin, vpSize)
+	local viewport = {};
 	
-	local point = vmath.vec3(points);
-	if(self.transform) then point = self.transform:Matrix():Transform(point) end;
+	viewport.pixelSize = vmath.vec2(pixelSize);
+	viewport.vpOrigin = vmath.vec2(vpOrigin);
+	viewport.pxCenter = viewport.pixelSize / 2;
+	if(type(vpSize) == "number") then vpSize = vmath.vec2(vpSize, vpSize) end;
+	viewport.vpSize = vmath.vec2(vpSize);
 	
-	point = point / self.vpSize;
-	point = point * vmath.vec2(1, -1);
-	point = point * self.pixelSize;
-	point = point + self.pxOrigin;
-	
-	return vmath.vec2(point);
+	AddMembers(viewport, View);
+	return viewport;
 end
 
-function View3D:SetTransform(transform)
-	self.transform = transform;
-end
-
-
 
 -- Transform 2D.
 local function Identity3()
 	self.currMatrix = self.currMatrix * rotation;
 end
 
+function Trans2D:MultMatrix(matrix)
+	self.currMatrix = self.currMatrix * matrix;
+end
+
 function Trans2D:Push()
 	if(not self.stack) then
 		self.stack = {};
 	return self.currMatrix;
 end
 
+function Trans2D:Vector(point)
+	return vmath.vec2(point);
+end
+
+function Transform2D()
+	local transform = {};
+	transform.currMatrix = Identity3();
+	AddMembers(transform, Trans2D);
+	return transform;
+end
+
 
 -- Transform 3D.
 local function Identity4()
 	self.currMatrix = self.currMatrix * rotation;
 end
 
+Trans3D.MultMatrix = Trans2D.MultMatrix;
+
 function Trans3D:Identity()
 	self.currMatrix = Identity4();
 end
 	return self.currMatrix;
 end
 
-
-
-function Transform2D()
-	local transform = {};
-	transform.currMatrix = Identity3();
-	AddMembers(transform, Trans2D);
-	return transform;
+function Trans3D:Vector(point)
+	return vmath.vec3(point);
 end
 
 function Transform3D()
 end
 
 
-function Viewport2D(pixelSize, pxOrigin, vpSize)
-	local viewport = {};
-	
-	viewport.pixelSize = vmath.vec2(pixelSize);
-	viewport.pxOrigin = vmath.vec2(pxOrigin);
-	if(type(vpSize) == "number") then vpSize = vmath.vec2(vpSize, vpSize) end;
-	viewport.vpSize = vmath.vec2(vpSize);
-	
-	AddMembers(viewport, View2D);
-	return viewport;
-end
-
-function Viewport3D(pixelSize, vpOrigin, vpScale)
-	local viewport = {};
-	
-	viewport.pixelSize = vmath.vec2(pixelSize);
-	viewport.vpOrigin = vmath.vec3(vpOrigin);
-	if(type(vpScale) == "number") then vpSize = vmath.vec3(vpSize, vpSize, vpSize) end;
-	viewport.vpScale = vmath.vec3(vpSize);
-	
-	AddMembers(viewport, View3D);
-	return viewport;
-end
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.