libgdx ModelInstance translating and rotating don't work - libgdx

My problem is i have a model (g3db) and
touchPosition.x = Gdx.input.getX();
touchPosition.y = Gdx.input.getY();
rotation.y = (float) Math.atan2(touchPosition.x - Gdx.graphics.getWidth() / 2, touchPosition.y - Gdx.graphics.getHeight() / 2) * MathUtils.radiansToDegrees + 90;
shipInstance.transform.translate(-10, 0, 0);
shipInstance.transform.setToRotation(new Vector3(0,1,0),rotation.y);
the ship is only rotating but not moving in the space.
What did i wrong?

Related

Draw a Pentagon with HTML 5 canvas

I need to draw a Pentagon with html 5 canvas in Javascript. Not much else to write here. I have tried looking it up, but a lot of the examples don't work correctly.
The pentagon starts at the 3oclock pos use rotation to change the start position in radians. ie To start at the top rotation is -90deg = -Math.PI / 2
function pentagon(x, y, radius, rotation){
for(var i = 0; i < 5; i ++){
const ang = (i / 5) * Math.PI * 2 + rotation;
ctx.lineTo(
Math.cos(ang) * radius + x,
Math.sin(ang) * radius + y
);
}
ctx.closePath();
}
ctx.beginPath();
pentagon(100,100,50,-Math.PI / 2);
ctx.fill();
ctx.stroke();

Rotating Angle Calculation AS3

I am writing a code where there are different rings on the stage, and a ball is rotating in one of these orbits. On click, the ball leaves its ring and travels normal to the ring. On its way if it hits another ring, it starts rotating in that ring from the point it hits the ring. I could successfully code the initial part of the code. but I am getting a problem when the ball hits another ring, it does not start from the location it hit. Instead it starts rotating in the ring from a different position. I hope I am clear with my doubt. It is somewhat similar to this game https://play.google.com/store/apps/details?id=com.drgames.orbit.jumper
here is my code in enter frame :
if(!isTravelling){
rad = Math.abs(angle * (Math.PI / 180)); // Converting Degrees To Radians
_ball.x = currOrbit.x + (currOrbit.width / 2) * Math.cos(rad); // Position The Orbiter Along x-axis
_ball.y = currOrbit.y + (currOrbit.width / 2) * Math.sin(rad); // Position The Orbiter Along y-axis
trace(_ball.x+" , "+_ball.y);
angle -= speed; // Object will orbit clockwise
_ball.rotation = (Math.atan2(_ball.y - currOrbit.y, _ball.x - currOrbit.x) * 180 / Math.PI) + 90;
}
for(var i = 0; i < orbits.length; i++){
if(orbits[i] != currOrbit){
if(ObjectsHit(orbits[i], _ball)){
currOrbit = orbits[i];
_ball.rotation = (Math.atan2(_ball.y - currOrbit.y, _ball.x - currOrbit.x) * 180 / Math.PI) + 90;
isTravelling = false;
stage.addEventListener(MouseEvent.CLICK, onClick);
}
}
}
if(isTravelling){
_ball.x += Math.cos(rad) * speed * 2;
_ball.y += Math.sin(rad) * speed * 2;
}
You seem to have forgotten to calculate the starting angle for the new orbit:
if(!isTravelling){
rad = Math.abs(angle * (Math.PI / 180)); // Converting Degrees To Radians
_ball.x = currOrbit.x + (currOrbit.width / 2) * Math.cos(rad); // Position The Orbiter Along x-axis
_ball.y = currOrbit.y + (currOrbit.width / 2) * Math.sin(rad); // Position The Orbiter Along y-axis
trace(_ball.x+" , "+_ball.y);
_ball.rotation = angle // no need for calculating the angle again
angle -= speed; // Object will orbit clockwise
}
for(var i = 0; i < orbits.length; i++){
if(orbits[i] != currOrbit){
if(ObjectsHit(orbits[i], _ball)){
currOrbit = orbits[i];
angle = (Math.atan2(_ball.y - currOrbit.y, _ball.x - currOrbit.x) * 180 / Math.PI) + 90; // Calculate the starting angle on the new orbit
_ball.rotation = angle // Set the balls rotation to the angle
isTravelling = false;
stage.addEventListener(MouseEvent.CLICK, onClick);
}
}
}
if(isTravelling){
_ball.x += Math.cos(rad) * speed * 2;
_ball.y += Math.sin(rad) * speed * 2;
}
This should fix it. Please note that you might have to add or subtract 90 degrees to your balls rotation (_ball.rotation = angle + 90) because im not 100% sure about that.

Scale rotated image to fill HTML5 Canvas using JavaScript trigonometry?

Below is the code I am currently using. With 0 rotation, the image is correctly scaled to fill the canvas. (similar to background-size: cover, except using JavaScript on a Canvas)
I'm trying to add a rotate feature, with the following features.
Keep image centered while rotating. I tried using width / 2 in translate, and then the opposite in drawImage, but as you can see the image did not stay centered. I'm not sure if this is a conflict with my earlier x and y centering code, or if trigonometry is required here?
Automatically scale the image further to cover the canvas. These are arbitrary rotations, not 90 degree increments. I don't want to crop any more of the image than necessary to fill the canvas corners. This is much more complex trigonometry than I am used to dealing with.
I think this can be done with Math.sin and Math.cos, but it's been a very long time since I've used them. I'm especially uncertain about how to achieve #2. Any help would be appreciated.
var canvas = document.querySelector('canvas')
var context = canvas.getContext('2d')
var image = new Image()
image.src = 'http://i.stack.imgur.com/7FsbT.jpg'
image.onload = function () {
var maxScaleX = canvas.width / image.width
var maxScaleY = canvas.height / image.height
scale = maxScaleX > maxScaleY ? maxScaleX : maxScaleY
var width = image.width * scale
var height = image.height * scale
var x = (width - canvas.width) / -2
var y = (height - canvas.height) / -2
var degrees = 30
context.setTransform(1, 0, 0, 1, 0, 0) // reset previous translate and/or rotate
context.translate(width / 2, height / 2)
context.rotate(degrees * Math.PI / 180)
context.drawImage(image, x - width / 2, y - height / 2, width, height)
}
<canvas width="350" height="150" style="border: solid 1px black"></canvas>
+1 to Blindman67's answer for this to work.
I shortened the code and simplified for my use case. You should be able to just include function drawBestFit() into your app and use it to fill any canvas with any loaded image.
For a better understanding of how this works, view Blindman67's original answer - especially the demonstration snippet at the bottom.
var canvas = document.querySelector('canvas')
var context = canvas.getContext('2d')
var image = new Image()
image.src = 'http://i.stack.imgur.com/7FsbT.jpg'
image.onload = function() {
var degrees = 0
loop()
function loop() {
degrees += .5
drawBestFit(context, degrees * Math.PI / 180, image)
requestAnimationFrame(loop)
}
function drawBestFit(ctx, angle, image) {
var dist = Math.sqrt(Math.pow(canvas.width, 2) + Math.pow(canvas.height, 2))
var diagAngle = Math.asin(canvas.height / dist)
var a1 = ((angle % (Math.PI * 2)) + Math.PI * 4) % (Math.PI * 2)
if (a1 > Math.PI)
a1 -= Math.PI
if (a1 > Math.PI / 2 && a1 <= Math.PI)
a1 = (Math.PI / 2) - (a1 - (Math.PI / 2))
var ang1 = Math.PI / 2 - diagAngle - Math.abs(a1)
var ang2 = Math.abs(diagAngle - Math.abs(a1))
var scale1 = Math.cos(ang1) * dist / image.height
var scale2 = Math.cos(ang2) * dist / image.width
var scale = Math.max(scale1, scale2)
var dx = Math.cos(angle) * scale
var dy = Math.sin(angle) * scale
ctx.setTransform(dx, dy, -dy, dx, canvas.width / 2, canvas.height / 2)
ctx.drawImage(image, -image.width / 2, -image.height / 2, image.width, image.height)
ctx.setTransform(1, 0, 0, 1, 0, 0) // reset transformations when done
}
}
<canvas width="350" height="200" style="border: solid 1px black"></canvas>

Separate fill for each shape in Flex graphics

I am drawing a bunch of circles in 2 horizontal rows across a sprite and would like a gradient applied to each circle individually but flex is applying it to the entire graphics area. What do I need to change to draw each circle with its own gradient?
var s:Sprite = new Sprite();
var g:Graphics = s.graphics;
g.beginBitmapFill(bd, new Matrix(), false, false);
g.drawRect(0, 0, s.width, s.height);
g.endFill();
var m:Matrix = new Matrix();
g.lineStyle(1, 0x888888, 1);
for(var i:int = 0; i < numSpirals; i++) {
g.beginGradientFill(GradientType.LINEAR, [0x666666, 0xFFFFFF], [1, 1], [0, 255], m);
xc = i * spiralWidth + spiralHoleRadius;
yc = bdCenter - (spiralBoxHeight / 2) + (spiralHoleRadius / 2);
g.drawCircle(xc, yc, spiralHoleRadius);
g.endFill();
}
for(i = 0; i < numSpirals; i++) {
g.beginGradientFill(GradientType.LINEAR, [0x666666, 0xFFFFFF], [1, 1], [0, 255], m);
xc = i * spiralWidth + spiralHoleRadius;
yc = bdCenter + (spiralBoxHeight / 2) - (spiralHoleRadius / 2);
g.drawCircle(xc, yc, spiralHoleRadius);
g.endFill();
}
Thanks for your help!
Edit - I forgot this part (may or may not be relevant). Before drawing the circles I drew the BitmapData from an ImageSnapshot of some UI elements onto the sprite as well.
Solution:
I needed to create a new matrix and 'createGradientBox' for each circle individually
m = new Matrix();
m.createGradientBox(spiralHoleRadius * 2, spiralHoleRadius * 2, 0, xc - spiralHoleRadius / 2, yc - spiralHoleRadius / 2);
Following is a simular question on this site, maybe it helps (I cannot comment so I put this in a answer)
AS3: beginGradientFIll() doesn't make me a gradient!

World to screen coordinates in LibGDX

I am trying to present a map on the screen and place pins on the map at certain coordinates that are predefined. currently the issue is when the screen size changes say from device to device or when running on a desktop when the window size changes the position of all the pins moves when the map is scaled to fit the screen. I'm sure there is an obvious was to make the positions dependent on the map size or something. Could someone point me in the right direction in terms of making the objects appear in the same locations when the screen scales?
You need to unproject your coordinates with your camera.
Let's say that your coordinates that you want to transform to 'screen' coordinates are called
screenX and screenY.
Vector3 vec=new Vector3(screenX,screenY,0);
camera.unproject(vec);
Now you can use your vec.x and vec.y values.
This is how you do it correctly
public static Vector3 MultiplyPoint(Matrix4 m, Vector3 point)
{
Vector3 result = new Vector3(0, 0, 0);
result.x = m.val[Matrix4.M00] * point.x + m.val[Matrix4.M01] * point.y + m.val[Matrix4.M02]* point.z + m.val[Matrix4.M03];
result.y = m.val[Matrix4.M10] * point.x + m.val[Matrix4.M11] * point.y + m.val[Matrix4.M12] * point.z + m.val[Matrix4.M13];
result.z = m.val[Matrix4.M20] * point.x + m.val[Matrix4.M21] * point.y + m.val[Matrix4.M22] * point.z + m.val[Matrix4.M23];
float num = m.val[Matrix4.M30] * point.x + m.val[Matrix4.M31] * point.y + m.val[Matrix4.M32] * point.z + m.val[Matrix4.M33];
num = 1f / num;
result.x *= num;
result.y *= num;
result.z *= num;
return result;
}
public static Vector2 WorldToScreenPoint(float x, float y)
{
Matrix4 V = Constants.Camera.view;
Matrix4 P = Constants.Camera.projection;
Matrix4 MVP = P.mul(V); // Skipping M, point in world coordinates
Vector3 screenPos = MultiplyPoint(MVP, new Vector3(x, y, 0));
Vector3 screenPoint = new Vector3(screenPos.x + 1f, screenPos.y + 1f, screenPos.z + 1f).scl(0.5f); // returns x, y in [0, 1] internal.
return new Vector2(screenPoint.x * Constants.GlobalWidth, screenPoint.y * Constants.GlobalHeight); // multiply by viewport width and height to get the actual screen coordinates.
}