Mapping a 2D object to 3D space, maintining 2D size - actionscript-3

I have a papervision3d sphere primitive that I am adding to a scene. The sphere is being sized with a radius of 285. However, because of my camera properties (zoom, focus and z) the sphere is rendering at 206px instead of 570px which is what I want (2 * radius).
A while back I found a blog post concerning this very issue and it was explained that you can set the z of any object in the scene to appear in 3D space the same size it would appear in 2D space by using the following:
mySphere.z = (this.camera.zoom * this.camera.focus) - Math.abs(this.camera.z) + radius;
The above worked when I was using several blocks, where radius was replaced with width/2. For some reason this does not work for the sphere.
Any ideas, pointers on how to get a sphere with a 570px diameter to show up on screen?
Thanks.

This cannot be achieved, at least not precisely. The perspective projection does not map a sphere to a circle. See how the spheres at the edges of this image are getting deformed?
(source: uni-stuttgart.de)

Related

Libgdx rotating ellipse for collision detection

I try to use 2 ellipses to detect a collision if they overlap. I have to rotate the ellipses but I can't figure out how this works. I'm working with the "com.badlogic.gdx.math.Ellipse" class but it seems to have no method for rotating. Any ideas? Thx in advance!!
Unfortunately, LibGDX doesn't have in-built rotating functions for ellipses.
Instead, I'd either be resorting to a circle in which rotation does not matter, or use polygons to check intersection.
Polygons are formed through an array of float values (vertices), where, every even element of the array is the horizontal component (x) and the odd, the vertical component (y).
Polygon polygon1 = new Polygon(vertexSet1);
Polygon polygon2 = new Polygon(vertexSet2);
Then, by using an Intersector, you can then check whether these polygons have intersected. The more vertices, the more accurate your shape will be. Just remember to have 6 or more elements in your vertex array, as the 6 floats will give 3 (x, y) points which is the minimum required for a polygon.
if (intersector.overlapConvexPolygons(polygon1, polygon2) {
//do your intersection code
}
The polygons themselves have commands to translate, scale and rotate, allowing for the rotations you mentioned above.

How composite sprites scale together with libgdx

I have composited my sprites to build a monster truck with customizable bumpers, cabs, spoilers wheels etc. The class that holds these Sprites is MTruck and I can draw it perfectly provided I stay with scale 1.0.
mWheels.setPosition(posX + 17 * scale, posY);
mCab.setPosition(posX + 22 * scale, posY + 7 * scale);
mFender.setPosition(posX, posY + 75 * scale);
mWheels is positioned at the y origin of the Truck and mFender at the x origin.
I've tried all sorts of values for scale and extracting it separate from the scale I apply to mWheels, mCab etc but all that happens is the sprites scale but their positions become misaligned.
I'm going to have to render to a texture and scale that as I whole if I can't crack this.
perhaps, Set origin could help you:
void setOrigin(float originX, float originY)
Sets the origin in relation to the sprite's position for scaling and
rotation.
float getOriginX()
The origin influences setPosition(float, float),
setRotation(float) and the expansion direction
of scaling setScale(float, float)
float getOriginY()
The origin influences setPosition(float, float),
setRotation(float) and the expansion direction of
scaling setScale(float, float)
http://libgdx.badlogicgames.com/nightlies/docs/api/com/badlogic/gdx/graphics/g2d/Sprite.html
NEW EDIT: maybe if you are customizing the vehicle on a menu for example, as is practicable after this the customized vehicle and create an image at runtime, and scale, an use this image in Sprite, for maybe it's easier, but it's just an idea

How do I correctly translate my map after scaling?

I'm creating a camera in canvas like the one in Super Smash Bros, where the center of the camera follows the center point of all players and scales to encompass all the players.
I have it set up to find the distance between the 2 players, and if it's larger than the canvas size, the camera scale lowers to decrease the size of the blocks, player sprites, etc.
ctx.scale(cameraS,cameraS);
ctx.translate(-(cameraX*cameraS)+(CANVAS_WIDTH/2),-(cameraY*cameraS)+(CANVAS_HEIGHT/2));
These are what scale and move the drawn images to a position relative to the screen.
This is the actual game using the code and as you can tell, the scaling and moving of the images is slightly incorrect, but I'm not sure why!
https://dl.dropboxusercontent.com/u/51784213/Conjugate/index.html
For reference, the red dot is the position centered between both players. The lines show the dead center of the actual canvas. When scaling is 1(no scaling at all), the red dot is completely centered as it should be. When the scaling starts to decrease, the red dot begins to move off center in weird directions.
For the code to be working correctly, the dot should be centered at all times, even during the scaling process!
Transformations are applied in the reverse order; so you are first translating and then scaling. This means that for a point (x, y), after the current transformation, you get
(
(x + CANVAS_WIDTH/2 - cameraX*cameraS) * cameraS,
(y + CANVAS_HEIGHT/2 - cameraY*cameraS) * cameraS
)
What's actually needed here is the canvas be translated by scaled (cameraX, cameraY) and then be offset by actual (CANVAS_WIDTH/2, CANVAS_HEIGHT/2), so that (cameraX, cameraY) is at center of the visible canvas.
Or rather, the transformation needed here for a point (x, y) is
(
(x - cameraX) * cameraS + CANVAS_WIDTH/2,
(y - cameraY) * cameraS + CANVAS_HEIGHT/2
)
Hence, the code becomes, if you choose to apply translate first,
ctx.scale(cameraS,cameraS);
ctx.translate(-cameraX+CANVAS_WIDTH/(2*cameraS),-cameraY+CANVAS_HEIGHT/(2*cameraS));
Or, if you choose to apply scaling first
ctx.translate(-cameraX*cameraS + CANVAS_WIDTH/2, -cameraY*cameraS + CANVAS_HEIGHT/2);
ctx.scale(cameraS, cameraS);
Working JSFiddle.

WebGL: canvas coordinates to 3d coords

I am trying to find the "left" border of my WebGL view port because I would like to draw a number of debug information there. (an axis mini map like most modeling programs have)
I certainly can get the width and height of the canvas containing the WebGL viewport.
I would really like to know how I would go about calculating 2d canvas coordinates to 3d coordinates? What would be the best approach to find the left border in the 3d viewport?
Anyone looking into this should read
http://webglfactory.blogspot.com/2011/05/how-to-convert-world-to-screen.html or take a look at GluProject() and GluUnproject()
To clarify datenwolf's answer, the coordinate mapping between your 3D space and 2D canvas is exactly what you want it to be. You control it with gl.viewport and the matrices that you pass to your shader.
gl.viewport simply blocks out a rectangle of pixels on your canvas that you are drawing to. Most of the time this matches the dimensions of your canvas exactly, but there are some scenarios where you only want to draw to part of it. (Split-screen gaming, for example.) The area of your canvas that you're drawing to will be referred to as the viewport from here on out. You can assume it means the same thing as "canvas" if you'd like.
At it's simplest, the viewport always has an implicit coordinate system from -1 to 1 on both the X and Y axis. This is the space that the gl_Position output by your vertex shader operates in. If you output a vertex at (-1, -1) it will be in the bottom left corner of your viewport. a vertex at (1, 1) will be in the top right. (Yes, I'm ignoring depth for now) Using this, you could construct geometry designed to map to that space and draw it without any matrix transforms at all, but that can be a bit awkward.
To make life easier, we use projection matrices. A projection matrix is simply one that transforms your geometry from some arbitrary 3D space into that -1 to 1 space required by the viewport. The most common one is a perspective matrix. How you create it will look a bit different depending on the library you use, but typically it's something like this:
var fov = 45;
var aspectRatio = canvas.width/canvas.height;
var near = 1.0;
var far = 1024.0;
var projectionMat = mat4.perspective(fov, aspect, near, far);
I'm not going to get into what all those values mean, but you can clearly see that we're using the canvas width and height to help set up this projection. That allows it to not look stretched or squashed depending on the canvas size. What it all boils down to, however, is that taking any 3D point in space and multiplying it by this matrix will produce a point that maps to that -1 to 1 space, taking into account distance from the 'camera' and everything else. (It may actually fall outside of that bounds, but that simply means it's off camera.) It's what makes our 3D scenes look 3D.
It's also possible to create an projection matrix specifically for drawing 2D geometry, though. This is called an orthographic matrix, and the setup typically looks something like this:
var left = 0;
var top = 0;
var right = canvas.width;
var bottom = canvas.height;
var near = 1.0;
var far = 1024.0;
var projectionMat = mat4.ortho(left, right, bottom, top, near, far);
This matrix is different than the perspective matrix in that it ignores the z component of your position entirely. Instead, this matrix transforms flat coordinates, like pixels, into the -1 to 1 range. As such, your scenes don't look 3D but it's easier to control exacty where things appear on screen. So, using the matrix above, if we give it a vertex at (16, 16, 0) it will appear at (16, 16) on our canvas (assuming the viewport is the same dimensions as the canvas). As such, when you want to draw things like flat UI elements this is the type of matrix you want!
The nice part is that because these are just values that you pass to a shader you can use completely different matrices from one draw call to the next. Typically you'll draw all of your 3D geometry with a perspective matrix, then all of your UI with a orthographic matrix.
Apologies if that was a bit rambling. I've never been terribly good at explaining all that math-y stuff.
I am trying to find the "left" border of my WebGL view port because I would like to draw a number of debug information there. (an axis mini map like most modeling programs have) I certainly can get the width and height of the canvas containing the WebGL viewport.
Just switch the viewport and projection for those parts. You can change them anytime.
See http://games.greggman.com/game/webgl-fundamentals
Basically if you want to draw in 2D use a 2D shader, don't try messing with a 3D shader.
WebGL draws in clipspace so all you need to do is convert from pixels to clip space.
attribute vec2 a_position;
uniform vec2 u_resolution;
void main() {
// convert positions from pixels to 0.0 to 1.0
vec2 zeroToOne = a_position / u_resolution;
// convert from 0->1 to 0->2
vec2 zeroToTwo = zeroToOne * 2.0;
// convert from 0->2 to -1->+1 (clipspace)
vec2 clipSpace = zeroToTwo - 1.0;
gl_Position = vec4(clipSpace * vec2(1, -1), 0, 1);
}
Why not just use some overlaid HTML?
<html>
<head>
<style>
#container {
position: relative;
}
#debugInfo {
position: absolute;
top: 0px;
left: 0px;
background-color: rgba(0,0,0,0.7);
padding: 1em;
z-index: 2;
color: white;
}
</style>
</head>
<body>
<div id="container">
<canvas></canvas>
<div id="debugInfo">There be info here!</div>
</div>
</body>
</html>
You can then update it with
var debugInfo = document.getElementById("debugInfo");
debugInfo.innerHTML = "some info";

understanding matrix.transition(); as3

I am trying to understand the method transition that falls in the Matrix Class. I am using it to copy pieces of a bitMapData. But I need to better understand what transitions do.
I have a tilesheet that has 3 images on it. all 30x30 pixels. the width of the total bitmap is 90pxs.
The first tile is green, the second is brown, and the third is yellow. If I move over 30pxs using the matrix that transitions, instead of getting brown, I get yellow, if I move over 60px, I get brown.
If I move -30 pixels, then the order is correct. I am confused on what is going on.
tileNum -= (tileNumber * tWidth);
theMatrix = new Matrix();
theMatrix.translate(tileNum,0);
this.graphics.beginBitmapFill(tileImage,theMatrix);
this.graphics.drawRect(0, 0,tWidth ,tHeight );
this.graphics.endFill();
Can someone tell me how transitions work, or some resources that show how they work. I ultimately want to know a good way to switch back and forth between each tile.
First of all, don't confuse translation with transition. The latter is a general English word for "change", whereas to translate in geometry and general math is to "move" or "offset" something.
A transformation matrix defines how to transform, i.e. scale, rotate and translate, an object, usually in a visual manner. By applying a transformation matrix to an object, all pixels of that object are rotated, moved and scaled/interpolated according to the values stored inside the matrix. If you'd rather not think about matrix math, just think of the matrix as a black box which contains a sequence of rotation, scaling, and translation commands.
The translate() method simply offsets the bitmap that you are about to draw a number of pixels in the X and Y dimensions. If you use the default ("identity") matrix, which contains no translation, the top left corner of your object/bitmap will be in the (0,0) position, known as the origin or registration point.
Consider the following matrix:
var mtx : Matrix = new Matrix; // No translation, no scale, no rotation
mtx.translate(100, 0); // translated 100px on X axis
If you use the above matrix with a BitmapData.draw() or Graphics.beginBitmapFill(), that means that the top left corner of the original bitmap should be at (x=100; y=0) in the target coordinate system. Sticking to your Graphics example, lets first consider drawing a rectangle without a matrix transformation.
var shape : Shape = new Shape;
shape.graphics.beginBitmapFill(myBitmap);
shape.graphics.drawRect(0, 0, 200, 200);
This will draw a 200x200 pixels rectangle. Since there is no transformation involved in the drawing method (we're not supplying a transformation matrix), the top left corner of the bitmap is in (x=0; y=0) of the shape coordinate system, i.e. aligned with the top left corner of the rectangle.
Lets look at a similar example using the matrix.
var shape : Shape = new Shape;
shape.graphics.beginBitmapFill(myBitmap, mtx);
shape.graphics.drawRect(0, 0, 200, 200);
This again draws a rectangle that is 200px wide and 200px high. But where inside this rectangle will the top left corner of myBitmap be? The answer is at (x=100, y=0) of the shape coordinate system. This is because the matrix defines such a translation.
But what then will be to the left of (x=100; y=0)? With the above code, the answer is that the bitmap repeats to fill the entire rectangle, and hence you will see the rightmost side of the bitmap, to the left of the leftmost side, as if there was another instance of the bitmap right next to it. If you want to disable the repeating image, set the third attribute of beginBitmapFill() to false:
shape.graphics.beginBitmpFill(myBitmap, mtx, false);
Lets take a look at one last example that might help your understanding. Remember that the translation matrix defines the position of the top left corner of an image, in the coordinate system of the shape. With this in mind, consider the following code, using the same matrix as before.
var shape : Shape = new Shape;
shape.graphics.beginBitmapFill(myBitmap, mtx);
shape.graphics.drawRect(100, 0, 100, 100);
Notice that this will draw the rectangle 100px in on the X axis. Not coincidentally, this is the same translation that we defined in our matrix, and hence the position of the top left corner of the bitmap. So even though repeating is enabled, we will not see a repeating image to the left of our rectangle, because we only start drawing at the point where the bitmap starts.
So the bottom line is, I guess, that you could think of the transform matrix as a series of transformation commands that you apply to your image as you draw it. This will offset, scale and rotate the image as it's drawn.
If you are curious about the inner workings of the matrix, Google transformation matrices, or read up on Linear Algebra!