What is the correct way to zoom in and out of a scene in SceneKit?
So when I enable the standard camera control in a scene and pinch in and out the scene gets bigger and smaller. What is that pinch really doing?
Is it changing the scale of the whole scene? Is it moving the camera closer?
I want to implement the same effect but programmatically.
What should I do to obtain the same effect?
When you pinch it's the field of view (xFox and yFov properties) of your camera that's changed. Changing the field of view is not the best way to zoom because it can dramatically change the perspective.
Moving the camera closer to your object is a good solution.
Also note that the "free camera" behavior is suitable for 3D viewers (such as Preview.app) but will rapidly become frustrating in any other app. At this point you might want to implement your own camera controller.
At any given point the camera has a position in space, it has a rotation for each of its own axis compared to each of the world axis, to have a zoom in and zoom out, you have to move the camera in the +z/-z axis direction.
Along the Cameras own Z/-Z axis.
For those on OSX, I used this in my SCNView subclass:
override func scrollWheel(theEvent: NSEvent) {
let cam = pointOfView!.camera
cam!.xFov = cam!.xFov - Double(theEvent.deltaY)
cam!.yFov = cam!.yFov - Double(theEvent.deltaY)
}
There are two (minor) problems that could be addressed with a little extra code. One is that the values can go negative, at which point the image is flipped inside-out. The other is that mouse acceleration can cause the zoom level to go too fast if you really spin the wheel. Limits on both of these would be a good idea, but in my app the behaviour was fine as it is above.
Related
i'm trying to create a 3D animation using WPF. To modelize a form i see that we can use PerspectiveCamera or matrixCamera. What's the difference between the both?
Perspective camera makes objects farther away look smaller, like what we see in real life or through a camera zoom lens. You can achieve the same thing using a matrix camera, but you can also do a lot more. The perspective camera and orthogonal camera are both special cases of the more general matrix camera. With a matrix camera, you could create a perspective in one dimension different from the other, like a panorama view. It requires more work than the other camera types to do the same thing, but has more possibilities.
I have an ximage which I want to zoom in on, and display. I'm currently taking the naive approach:
allocate bigger image
use nearest-neighbor interpolation to fill it in.
put the whole image on a pixmap.
Which works, but slowly, and crawls once I approach bigger zoom levels, like 800%. The gimp, however, can zoom in to 3200% and still feel snappy. What's the approach taken here? Should I only fill one screen at a time? But then what about scrolling: wouldn't performing interpolation, and an XPutImage, and an XCopyArea on each expose kill performance?
I'm not expert in Xlib, but in my opinion a good approach would be to draw only the zoomed part, instead of computing the interpolation of the entire image.
For scrolling, if you are looking for performances, you may copy the part of the old zoom which is still visible in the new position, and compute the interpolation of the "discovered" pixels. For example, when scrolling down, you may copy the bottom of the previous image and paste it higher, and then compute/draw the new visible stuff at the bottom.
Most modern X11 applications don't use Xlib directly much, if at all. My guess would be that Gimp is rendering the zoomed image into a buffer itself and drawing that to the window, rather than working with the image in an XImage.
Lets say I have a Canvas with one Image centered on the screen. When I move the image away from the center, lets say to the upper right corner, I want it to be skewed as if the Canvas was a perspective 3d-camera with a certain FOV. Can this be done somehow? Im playing around with the Perspective-property in Silverlight for WP7 but I cant get the effect Im after.
I believe this may be what you're looking for: How to Set this Kind of Perspective Transform in Matrix3D?
I'm currently using the Silverlight Map control for WP7, and am trying to visualize driving directions on the map. In order to highlight the route needed, I am using a MapLayer with a MapPolyline. The problem is that even with CacheMode set to BitmapCache, the MapPolyline area gets redrawn whenever the user pans or zooms the map. I've used other controls such as Ellipses or Pushpins, and with BitmapCache on, none of them redraw and give the same performance hit as MapPolyline.
Here's a quick example
<maps:Map ZoomLevel="3">
<maps:MapPolyline Name="line" Stroke="Red" StrokeThickness="9">
<maps:MapPolyline.CacheMode>
<BitmapCache/>
</maps:MapPolyline.CacheMode>
<maps:MapPolyline.Locations>
<maps:LocationCollection>
<geo:GeoCoordinate Latitude="33" Longitude="33"/>
<geo:GeoCoordinate Latitude="36" Longitude="33"/>
<geo:GeoCoordinate Latitude="33" Longitude="36"/>
</maps:LocationCollection>
</maps:MapPolyline.Locations>
</maps:MapPolyline>
</maps:Map>
If you set App.Current.Host.Settings.EnableRedrawRegions = true; you can see the redrawing that occurs. The performance is particularly bad when you have a larger polyline and zoom in closer.
Is there anything that can be done to help? The native Bing Maps has pretty smooth route drawing, so I would think that there should be a way to solve this?
Thanks!
Can you explain a bit more what the problem is?
I've got an app - RunSat - in which I draw polylines with several hundred points (e.g. I just looked at a 3 hour long bike ride) and this draws fine - including during zoom operations.
I don't understand the problem - even using the sample code above. To help - are you testing on a phone or on the emulator?
As for CacheMode and BitmapCache, I'm really not sure about using these settings for the map - I don't use them in RunSat if that helps - I just leave the phone alone to work out its own GPU drawing.
I have a few 3d rectangles on my screen that I want to pivot around the Y axis.
I want to press down with the mouse, and rotate the 3d object to a max rotation, but when the user moves their mouse, I want to slightly rotate it so that it looks like a see-saw (rotating from a range of -13 to 13 degrees on the Y-Axis).
At the moment, I can do this, but my frame rate really really suffers when I move the mouse quickly. So for example, when I click the left side of the rectangle, I generate a storyboard and animation objects, then rotate the 3d object to -13 degrees. Then when I slightly move the mouse to the right, I want to rotate it to -12.5, and so on...
Again, I can do all of this, its just that the performance suffers greatly! It goes down to 5-FPS in some cases... which is not acceptable.
My question is am I doing this the best way? How else could you animate a rotation base on the users position on the screen?
Thanks for any help you can provide!
Mark
I assume you are doing the following:
Using a separate Model3D for the object you are rotating & including it in a Model3DGroup
Giving it a RotateTransform3D containing an AxisAngleRotation3D
Animating the AxisAngle3D's Axis property in the Storyboard
If my assumptions are correct I think we can conclude the problem is efficiency in rendering, since the CPU required to update a single Axis value, recompute the Transform, and update MILCore is negligible.
I can think of several ways that could improve the rendering performance:
If your Model3D being rotated is a GeometryModel3D backed by a MeshGeometry3D, do as much as you can to simplify the mesh and the materials used. It can also help to substitute a different mesh for closeups.
If the Model3D being rotated is a GeometryModel3D that uses VisualBrush brushes, during animation temporarily replace the VisualBrush with an ImageBrush containing a BitmapImage that is a snapshot of the Visual underlying the VisualBrush as of the instant the animation starts. When the animation ends, put backthe VisualBrush. The user probably won't notice that the contents of the object freeze temporarily when it rotates. (Note that this same technique can be used if your Visual3D is a Viewport2DVisual3D.)
If the Model3D being rotated is combined into a Model3DGroup with other objects but lies entirely in front of or behind the other groups, separate the model into its own separate Viewport3DVisual, appropriately layered to get the effect you want.
Simplify lighting or Material types
Monitor the actual frame rate and if it is going too low when using the storyboard, rotate the object immediately to where the mouse indicates without using an animation.
MSDN presents some tips on what impacts in WPF 3D performance. If you didn't stumble on it yet, check the items on "Performance Impact: High" list.
Edit: In march 2009, Josh Smith published an article on CodeProject that involves rotating 3D objetcs. Maybe you want to check his solution.