Move object around cube’s corner without jittering using accelerometer - algorithm

I can move object (star) around cube’s corner using accelerometer. Object move following the orbit (green circle). Control inverted, if I tilt right object go left and vise versa.
While spinning cube around corner object move perfect. But when I stop spinning cube, object on one of the cube’s edges, cause of inverted control start jittering.
For example if I try to stop object between red and blue planes, it begins jumping from one plane to another.
Code for object movement
new accelX = abi_MTD_GetFaceAccelX(object.plane);
new accelY = abi_MTD_GetFaceAccelY(object.plane);
object.angle -= accelX - accelY;
if (object.angle >= 90) {
object.plane = GetRightPlane(object.plane);
object.angle -= 90;
} else if (object.angle <= 0) {
object.plane= GetBottomPlane(object.plane);
object.angle = 90 + spaceship.angle;
}
MovePointAlongCircle(OUT object.posX, OUT object.posY, object.orbit, object.angle);
Find coordinate on plane
const OBJECT _ORBIT_CENTER = 260;
new objectOrbit = 150;
MovePointAlongCircle(&posX, &posY, objectOrbit, anglePhi) {
posX = OBJECT_ORBIT_CENTER - (objectOrbit * cos(anglePhi));
posY = OBJECT _ORBIT_CENTER - (objectOrbit * sin(anglePhi));
}
I can get accelerometer values individually on each plane or like the cube is a one thing.
Trigonometric functions like sin and cos use fixed point and look up table.
I've got atan function, which return angle [-45; 45].
Atan(x) {
return ((PI_4_FIXED * x >> FP) - ((x * (ABS(x) - 256) >> FP) * (62 + (17 * ABS(x) >> FP)) >> FP)) * RAD_2_DEG >> FP;
}

Related

Processing - creating circles from current pixels

I'm using processing, and I'm trying to create a circle from the pixels i have on my display.
I managed to pull the pixels on screen and create a growing circle from them.
However i'm looking for something much more sophisticated, I want to make it seem as if the pixels on the display are moving from their current location and forming a turning circle or something like this.
This is what i have for now:
int c = 0;
int radius = 30;
allPixels = removeBlackP();
void draw {
loadPixels();
for (int alpha = 0; alpha < 360; alpha++)
{
float xf = 350 + radius*cos(alpha);
float yf = 350 + radius*sin(alpha);
int x = (int) xf;
int y = (int) yf;
if (radius > 200) {radius =30;break;}
if (c> allPixels.length) {c= 0;}
pixels[y*700 +x] = allPixels[c];
updatePixels();
}
radius++;
c++;
}
the function removeBlackP return an array with all the pixels except for the black ones.
This code works for me. There is an issue that the circle only has the numbers as int so it seems like some pixels inside the circle won't fill, i can live with that. I'm looking for something a bit more complex like I explained.
Thanks!
Fill all pixels of scanlines belonging to the circle. Using this approach, you will paint all places inside the circle. For every line calculate start coordinate (end one is symmetric). Pseudocode:
for y = center_y - radius; y <= center_y + radius; y++
dx = Sqrt(radius * radius - y * y)
for x = center_x - dx; x <= center_x + dx; x++
fill a[y, x]
When you find places for all pixels, you can make correlation between initial pixels places and calculated ones and move them step-by-step.
For example, if initial coordinates relative to center point for k-th pixel are (x0, y0) and final coordinates are (x1,y1), and you want to make M steps, moving pixel by spiral, calculate intermediate coordinates:
calc values once:
r0 = Sqrt(x0*x0 + y0*y0) //Math.Hypot if available
r1 = Sqrt(x1*x1 + y1*y1)
fi0 = Math.Atan2(y0, x0)
fi1 = Math.Atan2(y1, x1)
if fi1 < fi0 then
fi1 = fi1 + 2 * Pi;
for i = 1; i <=M ; i++
x = (r0 + i / M * (r1 - r0)) * Cos(fi0 + i / M * (fi1 - fi0))
y = (r0 + i / M * (r1 - r0)) * Sin(fi0 + i / M * (fi1 - fi0))
shift by center coordinates
The way you go about drawing circles in Processing looks a little convoluted.
The simplest way is to use the ellipse() function, no pixels involved though:
If you do need to draw an ellipse and use pixels, you can make use of PGraphics which is similar to using a separate buffer/"layer" to draw into using Processing drawing commands but it also has pixels[] you can access.
Let's say you want to draw a low-res pixel circle circle, you can create a small PGraphics, disable smoothing, draw the circle, then render the circle at a higher resolution. The only catch is these drawing commands must be placed within beginDraw()/endDraw() calls:
PGraphics buffer;
void setup(){
//disable sketch's aliasing
noSmooth();
buffer = createGraphics(25,25);
buffer.beginDraw();
//disable buffer's aliasing
buffer.noSmooth();
buffer.noFill();
buffer.stroke(255);
buffer.endDraw();
}
void draw(){
background(255);
//draw small circle
float circleSize = map(sin(frameCount * .01),-1.0,1.0,0.0,20.0);
buffer.beginDraw();
buffer.background(0);
buffer.ellipse(buffer.width / 2,buffer.height / 2, circleSize,circleSize);
buffer.endDraw();
//render small circle at higher resolution (blocky - no aliasing)
image(buffer,0,0,width,height);
}
If you want to manually draw a circle using pixels[] you are on the right using the polar to cartesian conversion formula (x = cos(angle) * radius, y = sin(angle) * radius).Even though it's focusing on drawing a radial gradient, you can find an example of drawing a circle(a lot actually) using pixels in this answer

Rotate a Sprite around another Sprite -libGDX-

video game link
I'm trying to make a game (see link above) , and I need to have the stick rotate around himself to maintain the orientation face to center of the circle.
this is how I declare the Sprite, and how I move it around the circle:
declaration:
line = new Sprite(new Texture(Gdx.files.internal("drawable/blockLine.png")));
line.setSize(140, 20);
lineX = Gdx.graphics.getWidth()/2 - line.getWidth()/2;
lineY = (Gdx.graphics.getHeight()/2 - line.getHeight()/2) + circle.getHeight()/2;
movement:
Point point = rotatePoint(new Point(lineX, lineY), new Point(Gdx.graphics.getWidth()/2, Gdx.graphics.getHeight()/2), angle+= Gdx.graphics.getDeltaTime() * lineSpeed);
line.setPosition(point.x, point.y);
rotatePoint function:
Point rotatePoint(Point point, Point center, double angle){
angle = (angle ) * (Math.PI/180); // Convert to radians
float rotatedX = (int) (Math.cos(angle) * (point.x - center.x) - Math.sin(angle) * (point.y-center.y) + center.x);
float rotatedY = (int) (Math.sin(angle) * (point.x - center.x) + Math.cos(angle) * (point.y - center.y) + center.y);
return new Point(rotatedX,rotatedY);
}
Any sugestions ?
I can't test right now but I think the rotation of the line should simply be:
Math.atan2(rotatedPoint.getOriginX() - middlePoint.getOriginX(), rotatedPoint.getOriginY() - middlePoint.getOriginY()));
Then you'll have to adjust rad to degrees or whatever you'll use. Tell me if it doesn't work!
I would take a different approach, I just created a method that places n Buttons around a click on the screen. I am using something that looks like this:
float rotation; // in degree's
float distance; //Distance from origin (radius of circle).
vector2 originOfRotation; //Center of circle
vector2 originOfSprite; //Origin of rotation sprite we are calculating
Vector2 direction = new vector2(0, 1); //pointing up
//rotate the direction
direction.rotate(rotation);
// add distance based of the direction. Warning: originOfRotation will change because of chaining method.
// use originOfRotation.cpy() if you do not want to init each frame
originOfSprite = originOfRotation.add(direction.scl(distance));
Now you have the position of your sprite. You need to increment rotation by x each frame to have it rotate. If you want the orientation of the sprite to change you can use the direction vector, probably rotated by 180 again. Efficiency wise I'm not sure what the difference would be.

Rotation is different after resizing movieclip

I am trying to implement transform methods to rotate and resize a movieclip at runtime and I have a problem when recalculating the rotation to follow the mouse.
I have a squared movieclip and a rotator object (a circle) at the right bottom corner of the square where I am listening for mouse events and on mouse move I do this:
_rotation = -(Math.atan2((event.stageX - this.x ), (event.stageY - this.y ))) * 180/Math.PI;
this.rotation = rotation + 45;//this is because my rotator object is on right,bottom corner
this works perfect as long as I don´t modify the width or height of the object but if I do modify then there is a small "jump" on the rotation of the object that I am not able of avoid.
I know this is due event.stageX and even.stageY are different as the rotator object, the one with the mouse listener, has moved after the resize event but no clue how to avoid the "jump".
Please excuse my bad English
You need to rotate the object around its center.
/**
* Rotates the object based on its center
* Parameters: #obj => the object to rotate
* # rotation => angle to rotate
* */
public function RotateAroundCenter(obj:Object, rotation:Number):void
{
var bound:Rectangle = new Rectangle();
// get the bounded rectangle of objects
bound = obj.getRect(this);
// calculate mid poits
var midx1:Number = bound.x + bound.width/2;
var midy1:Number = bound.y + bound.height/2;
// assign the rotation
obj.rotation = rotation;
// assign the previous mid point as (x,y)
obj.x = midx1;
obj.y = midy1;
// get the new bounded rectangle of objects
bound = obj.getRect(this);
// calculate new mid points
var midx2:Number = bound.x + bound.width/2;
var midy2:Number = bound.y + bound.height/2;
// calculate differnece between the current mid and (x,y) and subtract
//it to position the object in the previous bound.
var diff:Number = midx2 - obj.x;
obj.x -= diff;
diff = midy2 - obj.y;
obj.y -= diff;
}
Usage:
_rotation = -(Math.atan2((event.stageX - this.x ), (event.stageY - this.y ))) * 180/Math.PI;
RotateAroundCenter(this, rotation + 45);
Check this link

Quaternion translation and rotation in iOS OpenGL ES

I'm struggling with some quaternion code in iOS. I have an open cube, which i've rotated into an isometric view. i am able to rotate the cube with touch and rotate about its axis and also zoom in/out. I also have labels associated with the cube - which also need to rotate with the cube. Again, i've managed to do this.
However, i'm now trying to implement being able to drag the label (ie. translate it) from one position, to another. If we look at the image below, what i've tried to illustrate is that i want to be able to translate the label from "label from" to the position "label to". Then, when i come to rotating the cube, the label should stay in its new position and rotate with the cube. However, i'm making a cock-up of this translation and when i try rotating the cube, the label jumps to a new position since i've not set the label coordinates properly.
I have the quaternion associated with the cube.
With the following code, i have been able to translate the label properly when the quaternion is set to [0, 0, 0, 1] (so that the cube is front-on - looks like a square from this position).
- (void) rotateWithAngle:(float) radians andVector:(GLKVector3) axis andScale:(float) scale
{
if (radians != self.lastRadians
|| (axis.v[0] != self.lastAxis.v[0] || axis.v[1] != self.lastAxis.v[1] || axis.v[2] != self.lastAxis.v[2])
|| scale != self.lastScale)
{
GLKMatrix4 m = GLKMatrix4MakeTranslation(self.normX, self.normY, self.normZ);
if (radians != 0)
m = GLKMatrix4Rotate(m, radians, axis.x, -axis.y, axis.z);
m = GLKMatrix4Scale(m, scale, scale, scale);
float x = (m.m00 * m.m30) + (m.m01 * m.m31) + (m.m02 * m.m32) + (m.m03 * m.m33);
float y = (m.m10 * m.m30) + (m.m11 * m.m31) + (m.m12 * m.m32) + (m.m13 * m.m33);
float z = (m.m20 * m.m30) + (m.m21 * m.m31) + (m.m22 * m.m32) + (m.m23 * m.m33);
x /= m.m33;
y /= m.m33;
z /= m.m33;
float w = (((x+self.winSz) / (self.winSz * 2.0)) * self.parentFrame.size.width) + self.parentFrame.origin.x;
float h = (((y+self.winSz) / (self.winSz * 2.0)) * self.parentFrame.size.height) + self.parentFrame.origin.y;
self.lastRadians = radians;
self.lastAxis = axis;
self.lastScale = scale;
[self setCenter:CGPointMake(w,h)];
}
}
- (void) translateFromTouch:(UIPanGestureRecognizer *) pan
{
CGPoint translation = [pan translationInView:self];
CGPoint imageViewPosition = self.center;
GLKVector3 axis = GLKQuaternionAxis(*_quaternion);
float rot = GLKQuaternionAngle(*_quaternion);
CGFloat h = self.parentFrame.size.height;
CGFloat w = self.parentFrame.size.width;
imageViewPosition.x += translation.x;
imageViewPosition.y += translation.y;
self.center = imageViewPosition;
// recalculate the norm position
float x = ((2.0 * self.winSz * (imageViewPosition.x - self.parentFrame.origin.x)) / w) - self.winSz;
float y = ((2.0 * self.winSz * (imageViewPosition.y - self.parentFrame.origin.y)) / h) - self.winSz;
self.normX = x;
self.normY = y;
[pan setTranslation:CGPointZero inView:self];
}
These methods are hit if a label (based on a UILabel) is either dragged or the cube (or the opengl scene) is rotated.
This works when we are looking front-on, so that the x,y values can easily be converted from pixel coords into normal or world coords.
However, when the axis is not front-on, i'm struggling to figure it out. For instance, we we have the quaternion set at (0, sqrt(2)/2, 0, sqrt(2)/2) then all x translations correspond to z world coords. So how do i make this connection/calculation? I'm sure it's fairly easy but i've hit a wall with this.
(winSz i have set to 1.5. model coords very between -1 and 1)

Transform mouse coordinates to 3d coordinates

I have the following problem:
I have my mouse coordinates and I have a Model (Data Points) and I want the 3d Coordinates of my mouse coordinates and my lookAt Vector of this coordinates, so that I can make a raycast with the object, so that I can see the 3d values of the data points. So I want to click with the mouse and then I want to see the coordinates of the datapoint I clicked at.
I have the following from a tutorial, but it doesn't work. The ray origin and ray direction are not correct (I draw I line from ray origin in the ray direction and the ray origin isn't right:
Can anyone help me? Here is the code:
// Move the mouse cursor coordinates into the -1 to +1 range.
pointX = ((2.0f * (float)mouseX) / (float) screen_width) - 1.0f;
pointY = (((2.0f * (float)mouseY) / (float) screen_height) - 1.0f) * -1.0f;
m_D3D->GetProjectionMatrix(projectionMatrix);
pointX = pointX / projectionMatrix._11;
pointY = pointY / projectionMatrix._22;
// Get the inverse of the view matrix.
m_Camera->GetViewMatrix(viewMatrix);
D3DXMatrixInverse(&inverseViewMatrix, NULL, &viewMatrix);
// Calculate the direction of the picking ray in view space.
direction.x = (pointX * inverseViewMatrix._11) + (pointY * inverseViewMatrix._21)+
inverseViewMatrix._31;
direction.y = (pointX * inverseViewMatrix._12) + (pointY * inverseViewMatrix._22)
+ inverseViewMatrix._32;
direction.z = (pointX * inverseViewMatrix._13) + (pointY * inverseViewMatrix._23)
+ inverseViewMatrix._33;
// Get the origin of the picking ray which is the position of the camera.
origin = m_Camera->GetPosition();
// Get the world matrix and translate to the location of the sphere.
m_Impact->GetWorldMatrix(worldMatrix);
//D3DXMatrixTranslation(&translateMatrix, -5.0f, 1.0f, 5.0f);
//D3DXMatrixMultiply(&worldMatrix, &worldMatrix, &translateMatrix);
// Now get the inverse of the translated world matrix.
D3DXMatrixInverse(&inverseWorldMatrix, NULL, &worldMatrix);
D3DXVec3TransformCoord(&rayOrigin, &origin, &inverseWorldMatrix);
D3DXVec3TransformNormal(&rayDirection, &direction, &inverseWorldMatrix);
// Normalize the ray direction.
D3DXVec3Normalize(&rayDirection, &rayDirection);
//collision_object->setTransform(col_matrix);
collision_model->setTransform(col_matrix);
float collision_point[3];
//bool collision_result = collision_object ->rayCollision(rayOrigin,
rayDirection, true);
bool collision_result = collision_model ->rayCollision(rayOrigin,
rayDirection, true);
if(collision_result == true)
{
intersect = true;
//collision_object->getCollisionPoint(collision_point, true);
collision_model->getCollisionPoint(collision_point, false);
*coordX = collision_point[0];
*coordY = collision_point[1];
*coordZ = collision_point[2];
}
One simple way to build a ray from mouse is as follow (pseudo code)
Get mouse coords to -1 -> 1 range (as you already do)
Create view projection matrix (view*projection)
Invert it.
Create 2 mouse vectors:
near = Vector3(mousex,mousey,0);
far = Vector3(mousex,mousey,1);
rayorigin = transformcoord(near, inverseviewprojection);
rayend = transformcoord(far, inverseviewprojection);
raydir = normalize(rayend-rayorigin);

Resources