I'm having alot of trouble with the Google IO codelab for Tango https://io2015codelabs.appspot.com/codelabs/project-tango#1
After I finished it, it runs but it only turns, it doesnt move forward and backwars like the other tango apps in the play store.
I started on this yesterday but even after two days of debugging, I cannot get it to work right. Today I got so frustrated that I deleted everything and started over from scratch and it is still broken. I can get the permissions so I think tango is up and running, but not moving. I have enabled motion tracking and disabled/removed the scripts and code as specified in the tutorial. My PoseController looks like this:
using UnityEngine;
using System.Collections;
using Tango;
using System;
public class PoseController : MonoBehaviour , ITangoPose {
private TangoApplication m_tangoApplication; // Instance for Tango Client
private Vector3 m_tangoPosition; // Position from Pose Callback
private Quaternion m_tangoRotation; // Rotation from Pose Callback
private Vector3 m_startPosition; // Start Position of the camera
private Vector3 m_lastPosition; // last position returned in Unity coordinates.
// Controls movement scale, use 1.0f to be metric accurate
// For the codelab, we adjust the scale so movement results in larger movements in the
// virtual world.
private float m_movementScale = 10.0f;
// Use this for initialization
void Start ()
{
// Initialize some variables
m_tangoRotation = Quaternion.identity;
m_tangoPosition = Vector3.zero;
m_lastPosition = Vector3.zero;
m_startPosition = transform.position;
m_tangoApplication = FindObjectOfType<TangoApplication>();
if(m_tangoApplication != null)
{
RequestPermissions();
}
else
{
Debug.Log("No Tango Manager found in scene.");
}
}
// Permissions callback
private void PermissionsCallback(bool success)
{
if(success)
{
m_tangoApplication.InitApplication(); // Initialize Tango Client
m_tangoApplication.InitProviders(string.Empty); // Initialize listeners
m_tangoApplication.ConnectToService(); // Connect to Tango Service
}
else
{
AndroidHelper.ShowAndroidToastMessage("Motion Tracking Permissions Needed", true);
}
}
private void RequestPermissions()
{
// Request Tango permissions
m_tangoApplication.RegisterPermissionsCallback(PermissionsCallback);
m_tangoApplication.RequestNecessaryPermissionsAndConnect();
m_tangoApplication.Register(this);
}
// Pose callbacks from Project Tango
public void OnTangoPoseAvailable(Tango.TangoPoseData pose)
{
// Do nothing if we don't get a pose
if (pose == null) {
Debug.Log("TangoPoseData is null.");
return;
}
// The callback pose is for device with respect to start of service pose.
if (pose.framePair.baseFrame == TangoEnums.TangoCoordinateFrameType.TANGO_COORDINATE_FRAME_START_OF_SERVICE &&
pose.framePair.targetFrame == TangoEnums.TangoCoordinateFrameType.TANGO_COORDINATE_FRAME_DEVICE)
{
if (pose.status_code == TangoEnums.TangoPoseStatusType.TANGO_POSE_VALID)
{
// Cache the position and rotation to be set in the update function.
m_tangoPosition = new Vector3((float)pose.translation [0],
(float)pose.translation [1],
(float)pose.translation [2]);
m_tangoRotation = new Quaternion((float)pose.orientation [0],
(float)pose.orientation [1],
(float)pose.orientation [2],
(float)pose.orientation [3]);
}
else // if the current pose is not valid we set the pose to identity
{
m_tangoPosition = Vector3.zero;
m_tangoRotation = Quaternion.identity;
}
}
}
/// <summary>
/// Transforms the Tango pose which is in Start of Service to Device frame to Unity coordinate system.
/// </summary>
/// <returns>The Tango Pose in unity coordinate system.</returns>
/// <param name="translation">Translation.</param>
/// <param name="rotation">Rotation.</param>
/// <param name="scale">Scale.</param>
Matrix4x4 TransformTangoPoseToUnityCoordinateSystem(Vector3 translation,
Quaternion rotation, Vector3 scale)
{
// Matrix for Tango coordinate frame to Unity coordinate frame conversion.
// Start of service frame with respect to Unity world frame.
Matrix4x4 m_uwTss;
// Unity camera frame with respect to device frame.
Matrix4x4 m_dTuc;
m_uwTss = new Matrix4x4();
m_uwTss.SetColumn (0, new Vector4 (1.0f, 0.0f, 0.0f, 0.0f));
m_uwTss.SetColumn (1, new Vector4 (0.0f, 0.0f, 1.0f, 0.0f));
m_uwTss.SetColumn (2, new Vector4 (0.0f, 1.0f, 0.0f, 0.0f));
m_uwTss.SetColumn (3, new Vector4 (0.0f, 0.0f, 0.0f, 1.0f));
m_dTuc = new Matrix4x4();
m_dTuc.SetColumn (0, new Vector4 (1.0f, 0.0f, 0.0f, 0.0f));
m_dTuc.SetColumn (1, new Vector4 (0.0f, 1.0f, 0.0f, 0.0f));
m_dTuc.SetColumn (2, new Vector4 (0.0f, 0.0f, -1.0f, 0.0f));
m_dTuc.SetColumn (3, new Vector4 (0.0f, 0.0f, 0.0f, 1.0f));
Matrix4x4 ssTd = Matrix4x4.TRS(translation, rotation, scale);
return m_uwTss * ssTd * m_dTuc;
}
// FixedUpdate is called at a fixed rate
void FixedUpdate()
{
// Convert position and rotation from Tango's coordinate system to Unity's.
Matrix4x4 uwTuc = TransformTangoPoseToUnityCoordinateSystem(m_tangoPosition,
m_tangoRotation, Vector3.one);
Vector3 newPosition = (uwTuc.GetColumn(3))* m_movementScale;
Quaternion newRotation = Quaternion.LookRotation(uwTuc.GetColumn(2),
uwTuc.GetColumn(1));
// Calculate the difference in the poses received. This allows us
// to recover when we hit something in the virtual world.
Vector3 delta = newPosition - m_lastPosition;
m_lastPosition = newPosition;
Vector3 destination = rigidbody.position + delta;
Vector3 vectorToTargetPosition = destination - transform.position;
// If there is motion, move the player around the scene.
if(vectorToTargetPosition.magnitude > 0.1f)
{
vectorToTargetPosition.Normalize();
// Set the movement vector based on the axis input.
Vector3 movement = vectorToTargetPosition;
// Normalise the movement vector and make it proportional to the speed per second.
movement = movement.normalized * 5f * Time.deltaTime;
// Move the player to it's current position plus the movement.
rigidbody.MovePosition (transform.position + movement);
}
else {
rigidbody.velocity = Vector3.zero;
}
// always rotate, even if we don't move.
rigidbody.MoveRotation (newRotation);
// finally, let the game manager know the position of the player.
GameManager.Instance.PlayerPosition = transform.position;
}
}
That was just a copy and paste of what was in the codelab, so at this point there is none of my own code and still I cannot run this correctly. What am I doing wrong????
I've done some android development before tango but I'm fairly new to unity. However, I've double and triple checked everything and also my device says everything is up to date.
Thanks in advance!
It looks like the codelab has been updated and the last line in FixedUpdate was commented out "//GameManager.Instance.PlayerPosition = transform.position;".
https://io2015codelabs.appspot.com/codelabs/project-tango#7
Hope that helps.
Related
I have used Animation() method to make my view with the animation of scaling and Rotation. With the Rotation based on the Y axis, the default height and width of my view has been changed. It looks like the parallelogram.
rotation of rectangle along y-axis transformed to a parallelogram.
myview.Animate().RotationY(rotationangle)
.X(xposition)
.SetDuration(mduration)
.WithLayer()
.SetInterpolator(interpolate).Start();
My requirement:
I just want the rotation of my view no need to change its projection. How to restrict the rotation of rectangle along y-axis transformed to a parallelogram.
For more reference, please check the attached sample
now view be like,
Image
Please share your idea.
Thanks in Advance.
Note: while using PivotX and PivotY, there is no parallelogram shape. But I don't know the exact usage of that.
Regards,
Hemalatha Marikumar
is that not what are you looking for ?
it may work if you put this code in your current activity
Android: Temporarily disable orientation changes in an Activity
Do you want to create a 2D rotation?
You could try to use ScaleAnimation to rotate the view. If you want to rotate 360 degrees, you could use AnimationListener.
For example:
Button myview = (Button)FindViewById(Resource.Id.button2);
ScaleAnimation scaleAnimation = new ScaleAnimation(1, 0, 1, 1,
Android.Views.Animations.Dimension.RelativeToParent, 0.5f, Android.Views.Animations.Dimension.RelativeToParent, 0.5f);
ScaleAnimation scaleAnimation2 = new ScaleAnimation(0, 1, 1, 1,
Android.Views.Animations.Dimension.RelativeToParent, 0.5f, Android.Views.Animations.Dimension.RelativeToParent, 0.5f);
scaleAnimation.Duration = 4000;
scaleAnimation.SetAnimationListener(new AnimationListener(myview, scaleAnimation2));
scaleAnimation2.Duration = 4000;
myview.StartAnimation(scaleAnimation);
The Listener:
public class AnimationListener :Java.Lang.Object, IAnimationListener
{
View view;
Animation animation2;
public AnimationListener(View view, Animation animation)
{
this.view = view;
this.animation2 = animation;
}
public void OnAnimationEnd(Animation animation)
{
view.StartAnimation(animation2);
}
public void OnAnimationRepeat(Animation animation)
{
}
public void OnAnimationStart(Animation animation)
{
}
}
I am currently trying to rotate a positionVector (0,0,1) around the world's x-axis and then rotate it back to its original position (just trying to get it to work). I read into rotation matrixes and got it working (sorta) but i am pretty stuck now.
As the image and code shows i create a cube at the starting point (0,0,1) and rotate it down in this case 30 degrees. But it seems to rotate more than 30 degrees when rotating clockwise. However when i rotate it back counterclockwise (30 degrees) it does rotate the proper amount. Which results in it not ending up at its starting point as it should (0,0,1).
I was wondering if any of you could shed some light on why this is happening and how to fix it. Thank you guys in advance!
public float RotAngle = 330f;
public GameObject cube;
public GameObject original;
public GameObject relocator;
public GameObject initialTurn;
void Start ()
{
Vector3 pixelPos = new Vector3(0f, 0f, 1f);
original = GameObject.Instantiate(cube,pixelPos,Quaternion.identity) as GameObject;
original.name = "Original";
initialTurn = GameObject.Instantiate(cube, pixelPos, Quaternion.identity) as GameObject;
initialTurn.name = "InitialTurn";
relocator = GameObject.Instantiate(cube, pixelPos, Quaternion.identity) as GameObject;
relocator.name = "Relocator";
}
void Update()
{
initialTurn.transform.position = RotateAroundOrigin(original.transform.position, RotAngle*Mathf.Deg2Rad);
relocator.transform.position = RotateAroundOrigin(initialTurn.transform.position, (RotAngle * -1f) * Mathf.Deg2Rad);
}
Vector3 RotateAroundOrigin(Vector3 startPos,float angle)
{
startPos.Normalize();
startPos.y = (startPos.y * Mathf.Cos(angle)) - (startPos.z * Mathf.Sin(angle));
startPos.z = (startPos.y * Mathf.Sin(angle)) + (startPos.z * Mathf.Cos(angle));
return startPos.normalized;
}
You can rotate a direction vector pretty easily with a Quaternion.
Try this:
Vector3 RotateAroundOrigin(Vector3 startPos,float angle)
{
startPos.Normalize();
Quaternion rot = Quaternion.Euler(angle, 0.0f, 0.0f); // Rotate [angle] degrees about the x axis.
startPos = rot * startPos;
return startPos;
}
I would like to rotate a sprite on the scene by pressing the left or right arrows keys (think of the spaceship in Asteroids).
I have placed the sprite in question on the scene and created a script, but am not really certain of where to go from there.
My current script looks like this:
using UnityEngine;
using System.Collections;
public class RotateLeftRight : MonoBehaviour {
public float speed = 1.0f;
public string axisName = "Horizontal";
// Use this for initialization
void Start () {
}
// Update is called once per frame
void Update () {
if(Input.GetKeyDown(KeyCode.LeftArrow)) {
// left
transform.Rotate(-1.0f, 0.0f, 0.0f); // does nothing, just a bad guess
}
if(Input.GetKeyDown(KeyCode.RightArrow)) {
// right
transform.Rotate(1.0f, 0.0f, 0.0f); // does nothing, just a bad guess
}
}
}
I just coded the above without any knowledge of what would happen (and, hardly surprising, nothing appears to happen at all).
Any advice on how to rotate the sprite and control the speed of the rotation would be greatly appreciated.
I'm not able to try it with Unity right now, but my guess is that it is either rotating just 1º, so you are not able to notice it, or rotating 360º, and so it really stays the same.
Try to break down your problem:
Instead of transform.Rotate try transform.Translate(20f, 20f, 20f) just to make sure it is recognizing the input;
Use a different value instead of 1.0f, such as 0.1f and 30.0f (I think 30.0f would be 30º, but I'm not sure);
Try changing the rotation on the other axes y and z instead of x;
Use the alternative definition Rotate(Vector3 axis, float angle).
Hope it helps!
#Sailing Judo, here's the best answer if you want to rotate it like a wheel. Try observe again to your code and instead of putting/changing the X-axis as parameter, put your value at the Z-axis instead. Changing x or y-axis in a circular rotation ended up like flipping coins. Observe and try again.
if(Input.GetKey(KeyCode.LeftArrow)) {
// Clockwise
transform.Rotate(0, 0, -3.0f); // --> Instead of "transform.Rotate(-1.0f, 0.0f, 0.0f);"
}
if(Input.GetKey(KeyCode.RightArrow)) {
// Counter-clockwise
transform.Rotate(0, 0, 3.0f); // --> Instead of transform.Rotate(1.0f, 0.0f, 0.0f);
}
I am running this code on a PC (compiled in code::blocks 10.05)
When i used to do basic OpenGL code with GLUT (GL Utiltiy Toolkit) Everything worked fine.
Now that i'm running OpenGL code through the SDL Framework when i try to change the z-axis (third parameter) of the translation function the location of a geometric primitive (quad) the 3D space appears to have no depth and either shows covering the complete screen or completely disappears when the depth gets to a certain point.
Am i missing anything? :/
#include <sdl.h>
#include <string>
#include "sdl_image.h"
#include "SDL/SDL_opengl.h"
#include <gl\gl.h>
// Declare Constants
const int FRAMES_PER_SECOND = 60;
const int SCREEN_WIDTH = 640;
const int SCREEN_HEIGHT = 480;
const int SCREEN_BPP = 32;
// Create Event Listener
SDL_Event event;
// Declare Variable Used To Control How Deep Into The Screen The Quad Is
GLfloat zpos(0);
// Loop Switches
bool gamestarted(false);
bool exited(false);
// Prototype For My GL Draw Function
void drawstuff();
// Code Begins
void init_GL() {
glShadeModel(GL_SMOOTH); // Enable Smooth Shading
glClearColor(0.0f, 0.0f, 0.0f, 0.5f); // Black Background
glClearDepth(1.0f); // Depth Buffer Setup
glEnable(GL_DEPTH_TEST); // Enables Depth Testing
glDepthFunc(GL_LEQUAL); // The Type Of Depth Testing To Do
glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST); // Really Nice Perspective Calculations
glViewport(0, 0, 640, 513); // Viewport Change
glOrtho(0, 640, 0, 513, -1.0, 1.0); // Puts Stuff Into View
}
bool init() {
SDL_Init(SDL_INIT_EVERYTHING);
SDL_SetVideoMode(640, 513, 32, SDL_OPENGL);
return true;
}
void drawstuff() {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glTranslatef(0.0f, 0.0f, zpos);
glColor3f(0.5f,0.5f,0.5f);
glBegin(GL_QUADS);
glVertex3f(-1.0f, 1.0f, 0.0f);
glVertex3f( 1.0f, 1.0f, 0.0f);
glVertex3f( 1.0f,-1.0f, 0.0f);
glVertex3f(-1.0f,-1.0f, 0.0f);
glEnd();
}
int main (int argc, char* args[]) {
init();
init_GL();
while(exited == false) {
while( SDL_PollEvent( &event ) ) {
if( event.type == SDL_QUIT ) {
exited = true;
}
if( event.type == SDL_MOUSEBUTTONDOWN ) {
zpos-=.1;
}
}
glClear( GL_COLOR_BUFFER_BIT);
drawstuff();
SDL_GL_SwapBuffers();
}
SDL_Quit();
return 0;
}
When you say depth, do you refer to a perspective effect? You need to use a perspective projection matrix (see gluPerspective) if you want things farther away to appear smaller.
You're currently using orthographic projection (glOrtho), which does not have any perspective effect.
I don't know the reason for your problem, but I find a problem in your code.
After rendering one frame, you cleared the color framebuffer, but you forgot to clear the depth buffer.So, use glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); in your main function and see the effect.
I think I know the anwser:
In Orthographic projection(after projection and perspective divide):
Zb = -2/(f-n) -(f+n)/((f-n)*Z)
Zb:z value in depth buffer
Z: z value of your vertex you give
In your situation: glOrtho(0, 640, 0, 513, -1.0, 1.0);
f = 1.0, n = -1.0
so your Zb would always be -2/(f - n) = -1, this causes all your primitives's depth the same.
You can reference to Red book's Appendix C.2.5.There is a matrix for orthographic projection, and after that is perspective divide.
There is another tips to keep in mind in perspective projection that zNear value cannot be set to zero, which causes all primitives' depth value in depth buffer to be same as this one.
I'm trying to include support for zooming and rotating my camera class, around the centre of the viewport.
In my application, I've already positioned sprites manually before entering the SpriteBatch.Begin code, according to where the camera is positioned (to make culling easier to implement). Although each sprite is positioned manually, I would rather not rotate and scale each sprite individually.
I therefore am trying to use the matrixTransform argument on the SpriteBatch.Begin method.
Below is a hard-coded application I've made to illustrate the problem (using a Car.png content image). The rotation isn't as fast as I'd expect (10 degrees rotation every frame?), and it rotates/zooms about the top left. I would like it to rotate around the centre of the screen, which would always keep the middle car in the centre, and also scale from that point.
I have tried several combinations of creating matrix translations, reordering/adding/multiplying/translating by the halfway distance of viewport, but I don't really understand how matrices work. I've also tried the solutions on several websites which I haven't managed to make work for me.
Can someone tell me the matrix translations I have to create, or point me in the direction of a website you think will work for my setup?
Windows XNA application to demonstrate the problem:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.GamerServices;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Media;
namespace RenderTest
{
public class Game1 : Microsoft.Xna.Framework.Game
{
GraphicsDeviceManager graphics;
SpriteBatch spriteBatch;
Texture2D _carTexture;
float _zoom = 1.0f;
float _rotationInDegrees = 0.0f;
public Game1()
{
graphics = new GraphicsDeviceManager(this);
Content.RootDirectory = "Content";
}
protected override void LoadContent()
{
spriteBatch = new SpriteBatch(GraphicsDevice);
_carTexture = Content.Load<Texture2D>("Car");
}
protected override void Update(GameTime gameTime)
{
if (GamePad.GetState(PlayerIndex.One).Buttons.Back == ButtonState.Pressed)
this.Exit();
if (Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.Up)) // Zoom in key
_zoom *= 1.1f;
if (Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.Down)) // Zoom out key
_zoom /= 1.1f;
if (Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.Left)) // Rotate anticlockwise key
_rotationInDegrees -= 10;
if (Keyboard.GetState(PlayerIndex.One).IsKeyDown(Keys.Right)) // Rotate clockwise key
_rotationInDegrees += 10;
base.Update(gameTime);
}
protected override void Draw(GameTime gameTime)
{
GraphicsDevice.Clear(Color.CornflowerBlue);
spriteBatch.Begin(SpriteSortMode.Immediate, BlendState.AlphaBlend, SamplerState.LinearClamp, DepthStencilState.None, RasterizerState.CullNone, null, GetMatrix(GraphicsDevice));
spriteBatch.Draw(_carTexture, new Rectangle(0, 0, 50, 50), Color.White);//Square car placed top left
spriteBatch.Draw(_carTexture, new Rectangle(GraphicsDevice.Viewport.Width / 2 - 25, GraphicsDevice.Viewport.Height / 2 - 50, 50, 100), Color.Green);//Car placed centre
spriteBatch.Draw(_carTexture, new Rectangle(GraphicsDevice.Viewport.Width / 2 + 100, GraphicsDevice.Viewport.Height / 2 + 100, 50, 50), Color.Black);//Off centre but always within screen
spriteBatch.End();
base.Draw(gameTime);
}
Matrix GetMatrix(GraphicsDevice graphicsDevice)
{
Matrix translationMatrix = Matrix.CreateTranslation(0, 0, 0);
Matrix rotationMatrix = Matrix.CreateRotationZ(MathHelper.ToRadians(MathHelper.ToRadians(_rotationInDegrees)));
Matrix zoomMatrix = Matrix.CreateScale(_zoom);
Matrix compositeMatrix = translationMatrix * rotationMatrix * zoomMatrix;
return compositeMatrix;
}
}
}
Thanks,
Lee
Solution
Matrix GetMatrix(GraphicsDevice graphicsDevice)
{
Matrix translateToOrigin = Matrix.CreateTranslation(-graphicsDevice.Viewport.Width / 2, -graphicsDevice.Viewport.Height / 2, 0);
Matrix rotationMatrix = Matrix.CreateRotationZ(MathHelper.ToRadians(_rotationInDegrees));
Matrix zoomMatrix = Matrix.CreateScale(_zoom);
Matrix translateBackToPosition = Matrix.CreateTranslation(graphicsDevice.Viewport.Width / 2, graphicsDevice.Viewport.Height / 2, 0);
Matrix compositeMatrix = translateToOrigin * rotationMatrix * zoomMatrix * translateBackToPosition;
return compositeMatrix;
}
You should use the same Rectangle each time, and do the positioning in the matrix.
The reason for this is that the matrix is applied to your sprites after they are positioned using rectangle. All subseqent matrix operations will treat (0,0) as the origin, instead of the center of the texture as you expected.