Okay, this is driving me crazy. I've looked through tons of examples and can't seem to get quite what I need. I'm using XNA and I have a plane of vertices and my camera is up in the sky looking down on the vertices.
What I want is to rotate the camera around on the Y axis, basically get the same result as adjusting its YAW. However whenever I try to rotate around on the Y axis or adjust its YAW nothing actually happens. I can however get the effect I want by creating a Y rotation matrix on the world, but that doesn't feel like the "correct" way of doing it, I want the camera itself to spin and not the world. Here's a code snippet for what I have:
cameraPosition = Vector3.Transform(new Vector3(
cameraOffset.X - cameraOffset.X,
zoomAmount,
cameraOffset.Z - cameraOffset.Z),
Matrix.CreateRotationY(rotationAngle)) + cameraOffset;
view = Matrix.CreateLookAt(cameraPosition, cameraTarget, new Vector3(0, 0, 1));
Thanks!
Since you have the camera looking straight down, it sounds like what you want is for the camera to roll in local space. To roll your camera, you must rotate the Up vector you are feeding to the CreateLookAt(). Like this:
Vector3 newUp = Vector3.Transform(Vector3.UnitZ, Matrix.CreateRotationY(rotationAngle));
view = Matrix.CreateLookAt(cameraPosition, cameraTarget, newUp);
Related
I am quite new and experimenting with Apple's ARKit and have a question regarding rotation information of the ARCamera. I am capturing photos and saving the current position, orientation and rotation of the camera with each image taken. The idea is to create 2d plane nodes with these images and have them appear in another view in the same position/orientation/rotation (with respect to the origin) as when when they were captured (as if the images were frozen in the air when they were captured). The position information seems to work fine, but the orientation/rotation comes up completely off as I’m having a difficulty in understanding when it’s relevant to use self.sceneView.session.currentFrame?.camera.eulerAngles vs self.sceneView.pointOfView?.orientation vs self.sceneView.pointOfView?.rotation.
This is how I set up my 2d image planes:
let imagePlane = SCNPlane(width: self.sceneView.bounds.width/6000, height: self.sceneView.bounds.height/6000)
imagePlane.firstMaterial?.diffuse.contents = self.image//<-- UIImage here
imagePlane.firstMaterial?.lightingModel = .constant
self.planeNode = SCNNode(geometry: imagePlane)
Then I set the self.planeNode.eulerAngles.x to the value I get from the view where the image is being captured using self.sceneView.session.currentFrame?.camera.eulerAngles.xfor x (and do the same for y and z as well).
I then set the rotation of the node as self.planeNode.rotation.x = self.rotX(where self.rotX is the information I get from self.sceneView.pointOfView?.rotation.x).
I have also tried to set it as follows:
let xAngle = SCNMatrix4MakeRotation(Float(self.rotX), 1, 0, 0);
let yAngle = SCNMatrix4MakeRotation(Float(self.rotY), 0, 1, 0);
let zAngle = SCNMatrix4MakeRotation(Float(self.rotZ), 0, 0, 1);
let rotationMatrix = SCNMatrix4Mult(SCNMatrix4Mult(xAngle, yAngle), zAngle);
self.planeNode.pivot = SCNMatrix4Mult(rotationMatrix, self.planeNode.transform);
The documentation states that eulerAngles is the “orientation” of the camera in roll, pitch and yaw values, but then what is self.sceneView.pointOfView?.orientation used for?
So when I specify the position, orientation and rotation of my plane nodes, is the information I get from eulerAngles enough to capture the correct orientation of the images?
Is my approach to this completely wrong or am I missing something obvious? Any help would be much appreciated!
If what you want to do is essentially create a billboard that is facing the camera at the time of capture then you can basically take the transform matrix of the camera (it already has the correct orientation) and just apply an inverse translation to it to move it to the objects location. They use that matric to position your billboard. This way you don't have to deal with any of the angles or worry about the correct order to composite the rotations. The translation is easy to do because all you need to do is subtract the object's location from the camera's location. One of the ARkit WWDC sessions actually has an example that sort of does this (it creates billboards at the camera's location). The only change you need to make is to translate the billboard away from the camer's position.
So I have a bit of a project I am trying to do. I am trying to get the devices rotation relative to gravity, and translation from where it started. So basically getting "tracking" data for the device. I plan to basically apply this by making a 3d pt that will mimic the data I record from the device later on.
Anyway to attempt to achieve this I thought it would be best to work with scene kit that way I can see things in 3 dimensions just like the data I am trying to record. Right now I have been trying to get the ship to rotate so that it always looks like its following gravity (like its on the ground or something) no mater what the device rotation is. I figure once I have this down it will be a sinch to apply this to a point. So I made the following code:
if let attitude = motionManager.deviceMotion?.attitude {
print(attitude)
ship.eulerAngles.y = -Float(attitude.roll)
ship.eulerAngles.z = -Float(attitude.yaw)
ship.eulerAngles.x = -Float(attitude.pitch)
}
When you only run one of the rotation lines then everything is perfectly. It does behave properly on that axis. However when I do all three axis' at once it becomes chaotic and performs far from expected with jitter and everything.
I guess my question is:
Does anyone know how to fix my code above so that the ship properly stays "upright" no matter what the orientation.
J.Doe!
First there is a slight trick. If you want to use the iphone laying down as the default position you have to notice that the axis used on sceneKit are different then those used by the DeviceMotion. Check the axis:
(source: apple.com)
First thing you need to set is the camera position. When you start a SceneKit project it creates your camera in the position (0, 0, 15). There is a problem with that:
The values of eulerAngles = (0,0,0) would mean the object would be in the plane xz, but as long as you are looking from Z, you just see it from the side. For that to be equivalent to the iphone laying down, you would need to set the camera to look from above. So it would be like you were looking at it from the phone (like a camera, idk)
// create and add a camera to the scene
let cameraNode = SCNNode()
cameraNode.camera = SCNCamera()
scene.rootNode.addChildNode(cameraNode)
// place the camera
cameraNode.position = SCNVector3(x: 0, y: 15, z: 0)
// but then you need to make the cameraNode face the ship (the origin of the axis), rotating it
cameraNode.eulerAngles.x = -Float(M_PI)*0.5 //or Float(M_PI)*1.5
With this we are going to see the ship from above, so the first part is done.
Now we gotta make the ship remain "still" (facing the ground) with the device rotation.
//First we need to use SCNRendererDelegate
class GameViewController : UIViewController SCNSceneRendererDelegate{
private let motion = CMMotionManager();
...
Then on viewDidLoad:
//important if you remove the sceneKit initial action from the ship.
//The scene would be static, and static scenes do not trigger the renderer update, setting the playing property to true forces that:
scnView.playing = true;
if(motion.deviceMotionAvailable){
motion.startDeviceMotionUpdates();
motion.deviceMotionUpdateInterval = 1.0/60.0;
}
Then we go to the update method
Look at the axis: the axis Y and Z are "switched" if you compare the sceneKit axis and the deviceMotion axis. Z is up on the phone, while is to the side on the scene, and Y is up on the scene, while to the side on the phone. So the pitch, roll and yaw, respectively associated to the X, Y and Z axis, will be applied as pitch, yaw and roll.
Notice I've put the roll value positive, that's because there is something else "switched". It's kinda hard to visualize. See the Y axis of device motion is correlated to the Z axis of the scene. Now imagine an object rotation along this axis, in the same direction (clock-wise for example), they would be going in opposite directions because of the disposition of the axis. (you can set the roll negative too see how it goes wrong)
func renderer(renderer: SCNSceneRenderer, updateAtTime time: NSTimeInterval) {
if let rot = motion.deviceMotion?.attitude{
print("\(rot.pitch) \(rot.roll) \(rot.yaw)")
ship.eulerAngles.x = -Float(rot.pitch);
ship.eulerAngles.y = -Float(rot.yaw);
ship.eulerAngles.z = Float(rot.roll);
}
Hope that helps! See ya!
I wonder how I can track the head position and rotation with kinect sdk!
Is it possible? If yes how?
And whatabout tracking the entire body rotation?? (y-axis)
Please c# code would be grateful ;-)
Absolutely Kinect SDK provides head rotation against X, Y, and Z axis using Face Tracking.
In OnFrameReady method, please construct FaceTracker object with Kinect Sensor as its parameter.
this.faceTracker = new FaceTracker(kinectSensor);
Create FaceTrackFrame object using .Track() method of facetracker.
FaceTrackFrame frame = this.faceTracker.Track(colorImageFormat, colorImage, depthImageFormat, depthImage, skeletonOfInterest);
Get X, Y , Z head rotation axis :
float yRotation = frame.Rotation.Y;
float xRotation = frame.Rotation.X;
float zRotation = frame.Rotation.Z;
FYI about head rotation using Face Tracking, here is the documentation :
http://msdn.microsoft.com/en-us/library/jj130970.aspx
About body rotation, I haven't tried any experiment on it.
as far as I know, there isn't a way to track rotation. The best way you could go about doing so would be to compare the Left Shoulder and Right Shoulder, or the Left Hip and Right Hip, and determine each Z axis to see which is closer and then you can get an idea of which way the body is rotated.
I'm looking to Animate a UIView and give it some 3D Effects.
I've experimented with CATransform3DMakeRotation() but can't seem to get the correct effect.
What I am trying to achieve is something like this:
Where the red view is moving from side to side with a 3d perspective.
Not the exact answer, but something to point you to right direction. Tumbljack has a nice tutorial, sample project and video on how to do 3D transformation on a view.
You can try with the following properties as mentioned in that.
layer.transform = CATransform3DMakeRotation(radian, x, y, z);
or
transform.m34 = 1.0 / -zDistance;
Try tweaking the sample code to get the desired output on your UIVIew. His tutorial is to have a complete 3D cube/sphere transformation and in your case you might need only the left and right movement from that.
Okay guys, I have spent a good two weeks trying to figure this out. I've tried some of my own ways to work this out by math alone and had no success. I also looked everywhere and have seen people recommend Viewport.Project().
This is not that simple. Everywhere I've looked, including MSDN areas and all forums, just suggest to be able to use it but as I try and use it they don't explain the matrix and values it requires to work. I have found no useful information on how to correctly use this method and it's seriously driving me insane. Please help this poor fella out.
First thing Im going to do is post my current code. I have five or so different versions none of them have worked. The closest I got was getting NAN which I don't understand. I'm trying to have text displayed on my screen based on where asteroids are and if they are very far the text will act as a guide so players can go to asteroids.
Vector3 camLookAt = Vector3.Zero;
Vector3 up = new Vector3(0.0f, 0.0f, 0.0f);
float nearClip = 1000.0f;
float farClip = 100000.0f;
float viewAngle = MathHelper.ToRadians(90f);
float aspectRatio = (float)viewPort.Width / (float)viewPort.Height;
Matrix view = Matrix.CreateLookAt(new Vector3(0, 0, 0), camLookAt, up);
Matrix projection = Matrix.CreatePerspectiveFieldOfView(viewAngle, aspectRatio, nearClip, farClip);
Matrix world = Matrix.CreateTranslation(camPosition.X, camPosition.Y, 0);
Vector3 projectedPosition = graphicsDevice.Viewport.Project(new Vector3(worldPosition.X, worldPosition.Y, 0), projection, view, Matrix.Identity);
screenPosition.X = projectedPosition.X;
screenPosition.Y = projectedPosition.Y;
if (screenPosition.X > 400) screenPosition.X = 400;
if (screenPosition.X < 100) screenPosition.X = 100;
if (screenPosition.Y > 400) screenPosition.Y = 400;
if (screenPosition.Y < 100) screenPosition.Y = 100;
return screenPosition;
As far as I know Project is the camera position. My game is 2D so vector3 is annoying I thought maybe my Z could be CameraZoom, projection might be the object we want to convert to 2D Screen, view might be the size of how much the camera can see, and the last one I'm not sure.
After about 2 weeks of searching for information with no possible improvements in code or knowledge and being more confused as I look at MDSN tutorials I decided I'd post a question because I'm extremely close to just not implementing world position convert to screen position. All help is appreciated thanks :)
Plus I'm using a 2D game and it does add confusion when most times people talk about the Z axis when a 2D game does not have a Z axis its just transforming sprites to appear like a zoom or movement. Thanks again :)
I may be misunderstanding here, but I don't think you need to be using a 3D camera provided with XNA for a 2D game. Unless you're trying to make a 2.5D game using 3D for some sort of parallax system or whatever, you don't need to use that at all. Take a look at these:
2D Camera Implemetation in XNA
Simpler 2D Camera
XNA 2D tutorials
2D in XNA works differently than 3D. You don't need to worry about the 3D viewport or a 3D camera or anything. There is no nearclipping or farclipping. 2D is well-handled in XNA and I think you are misunderstanding a bit how XNA works.
PS: You don't need to use Vector3s. Instead, use Vector2s. I think you will find them much easier to work with in a 2D game. ^^