I'm writing a small CAD application in Qt 5.1 and I'm trying to figure out how to get the coordinates of the QGraphicsScene to correspond to real-world dimensions. I intend to keep coordinates in their original form of (value, unit) to preserve data when switching from mm to inches, for example.
I've found in their documentation (http://qt-project.org/doc/qt-4.8/coordsys.html) that the default unit corresponds to 1 pixel on pixel-based paint devices and 1/72 inch for print-based devices.
Is this the conversion I should use (72 units per inch)? That's not particularly convenient... Is there a better way to associate real-world dimensions with the coordinates in a QGraphicsScene? Can this conversion be adjusted?
Thanks :)
Relativity is the important thing here and there's no direct correlation between what you see in a QGraphicsScene and the real-world, unless you decide to create a representative scale.
You can happily create a molecular model to scale, of atoms inside an object, or you could model a solar system that allows you to travel between stars and galaxies. What is important is what you as the developer decide your scale is going to be.
In a solar system, going from a GraphicsScene coordinate position of (0,0) to (10,0) could mean a distance of 10 meters or 10 miles. So long as the objects in the scene are modelled to the same scale and positioned in the scene using that scale, that's what matters.
When it comes to printing, I agree with #FrankOsterfeld that it's a matter of scaling the view on the scene. If you want a direct correlation between what you see on screen and what you print on paper, you'd be better off not using a QGraphicsScene here.
Related
I am hoping someone might be able to point me in the right direction (or let me know if I'm on the right path).
I am trying to build an image editing application that uses computer vision to assist with virtual object insertion - Basically AR but with the constraint of a single monocular image (uncalibrated).
The virtual object insertion will only occur on the ground plane (eg think of a virtual rug on the floor). Because of this (much like AR) I will need to align a virtual camera with the physical camera and composite the rendered virtual scene with the physical image.
I have had success training a semantic segmentation deep CNN to predict the flooring of an indoor scene (which serves as a mask, so that the virtual object, eg rug, is only visible in this area), but I am running into difficulties determining the camera properties.
My intuition is that in order to build a virtual scene that can be composited, the camera calibration properties that I care about is the height of the camera, the pitch, the roll and the field of view (or focal length). Now because this is just for rendering purposes, the estimated values don't need to be super accurate, just close enough that a rendered object doesn't look distorted.
After researching the problem I have come across this paper Single View Metrology In the Wild - It appears to provide an estimate for all of the calibration properties as listed above. With that said, with no training code available, this may end up taking quite a long time for something that may or may not work - although one I am willing to investigate if this is the only option.
Am I missing an obvious approach here? I've read some papers around more traditional CV approaches (eg vanishing points) and some more modern approaches (eg UprightNet), but they usually are missing one of the necessary camera calibration values listed above.
You can get camera parameters by calibrating it according to OpenCV docs. Have you tried that?
Eh, "more modern"... Canoma was released in 1998 IIRC, and was based in part on work done earlier by Paul Devevec at UCB. Both showed that realistic CG insertion on single image was doable with very little/easy user input.
The software calibrated the camera's focal length and pose by having the user trace with the mouse a few boxes or cylinders matching structures in view (e.g. buildings, towers). With a little practice, one or two boxes were all that was needed to get a good solution.
This question already has answers here:
How to render ocean wave using opengl in 3D? [closed]
(2 answers)
Closed 7 years ago.
I have absolutely no idea how to render water sources (ocean, lake, etc). It's like every tutorial I come across assumes I have the basic knowledge in this subject, and therefore speaks abstractly about the issue, but I don't.
My goal is to have a height based water level in my terrain.
I can't find any good article that will help me get started.
The question is quite broad. I'd split it up into separate components and get each working in turn. Hopefully this will help narrow down what those might be, unfortunately I can only offer the higher level discussion you aren't directly after.
The wave simulation (geometry and animation):
A procedural method will give a fixed height for a position and time based on some noise function.
A very basic idea is y = sin(x) + cos(z). Some more elaborate examples are in GPUGems.
Just like in the image, you can render geometry by creating a grid, sampling heights (y) at the grid x,y positions and connecting those points with triangles.
If you explicitly store all the heights in a 2D array, you can create some pretty decent looking waves and ripples. The idea here is to update height based on the neighbouring heights, using a few simple rules. For example, each height moves towards the average neighbouring height but also tends towards the equilibrium height equals zero. For this to work well, heights will need a velocity value to give the water momentum.
I found some examples of this kind of dynamic water here:
height_v[i][j] += ((height_west+ height_east + height_south + height_north)/4 - height[i][j]);
height_v[i][j] *= damping;
height[i][j] += height_v[i][j];
Rendering:
Using alpha transparency is a great first step for water. I'd start here until your simulation is running OK. The primary effect you'll want is reflection, so I'll just cover that. Further on you'll want to scale the reflection value using the Fresnel ratio. You may want an absorption effect (like fog) underwater based on distance (see Beer's law, essentially exp(-distance * density)). Getting really fancy, you might want to render the underneath parts of the water with refraction. But back to reflections...
Probably the simplest way to render a planar reflection is stencil reflections, where you'd draw the scene from underneath the water and use the stencil buffer to only affect pixels where you've previously drawn water.
An example is here.
However, this method doesn't work when you have a bumpy surface and the reflection rays are perturbed.
Rather than render the underwater reflection view directly to the screen, you can render it to a texture. Then you have the colour information for the reflection when you render the water. The tricky part is working out where in the texture to sample after calculating the reflection vector.
An example is here.
This uses textures but just for a perfectly planar reflection.
See also: How do I draw a mirror mirroring something in OpenGL?
Let's say that I have a perspective view in OpenGL and choose a point at a given depth. Let's say that it's at z=-10. How do I know which actual x- and y-coordinates this point have? It is easy when having an orth view because it then is the same for every depth. but for the perspective one: How do I find these x-y-values?
The coordinates you supply are basically "world" coordinates -- i.e., where things exist in the virtual world you build. In other words, the coordinates you work with are always orthogonal.
Just for example, if I was going to do a 3D model of a house, I could set it up so I was working in actual feet, so when I could draw a line from 0,0 to 0,10 to represent something exactly 10 feet long. That would remain 10 feet whether I viewed it up close, so it filled my view, or from a long ways away so it was only a couple of pixels long.
Only when objects are being displayed is perspective transformation done. I don't do it on the coordinates being fed into the system at all.
If you're asking about computing the screen coordinates for an object, yes, you can. The usual way to do this is with gluUnProject. At least in my experience it's relatively unusual that you end up needing to do this though.
The one time you sort of care is when you're selecting something on-screen using the mouse. Though it's possible to do with with gluUnProject, OpenGL has a selection mode that's intended specifically for this kind of purpose, and it works pretty well.
Look at gluProject as a way of projecting your cursor position into a "world" position (and gluUnproject as a way of finding out where your object is on screen).
At the moment i use 45 degree angle for my gluPerspective(). Is this the correct angle to make the rendering look realistic in how humans perceive it? Also there is an issue with the window aspect ratio, for example 2:1 window will make 45 degree angle look more like 80 degree angle on a screen with 3:4 ratio etc. So the window size changes the perspective as well.
So what is the correct window size ratio and field of view angle for making a game look most realistically compared to how humans perceive the world?
Unless you're using some kind of wrap-around setup, a single monitor isn't going to fill up the entire field of view of the human eye, which is usually nearly 180 degrees horizontally (of course it varies from person to person). If you tried to render something that wide, it would look weird -- the scene would appear to stretch out excessively toward the edges. Set the FOV to 120 degrees or so and you'll see what I'm talking about.
So instead of considering the human eye's FOV, you usually just draw imaginary lines from the user's head to the edges of the monitor, and take the angles between those. Of course this varies from desk to desk, monitor to monitor, so it's something of an artistic decision. 70 degrees vertical is decent place to start with. Assuming the game is running full screen, you're basically at the mercy of the monitor itself for the aspect ratio.
In general, unless you have very specific needs, you should give the user the option to change the FOV as they see fit.
You also generally do not want to have your monitor's FOV conform to the human range of FOV. After all, the monitor only covers part of a human's visual range; even if they're not paying attention to anything else, they still see everything around it. Most people are fine with having their monitor be a portal-like view of a world.
its around 87
most games seem to use a random center point, so eye to monitor edge is not correct either.
there should also be an adjustment for depth so the screen appears to be no more than a glass pane.
you know when you find one that works, your brain takes it all in very easily and your aim will be perfect as your muscle memory can react instantly.
(guess what, I'm not fine with a portal view :)
How does one have a scrolling map and detect collision on it?
I have tried a tile map but dont want to use this technique.
I would like to learn how a games background can be scrolled as well as object are detected for collision.
One example would be this game.
If one is not using tilemaps for this, how is the world scrollable as well as having physical objects detecting collision with the character sprite?
Please point me in the right direction on this topic.
Simple collision detection is done by checking to see if bounding boxes (or sometimes, bounding circles) overlap. That is, given object A and object B, if their bounding boxes overlap, then a collision has occurred.
If you want to get fancy, you create polygons for your objects and determine if the bounding polygons overlap. That's more complicated and harder to get right, and also involves considerably more processing.
It's not really much different from using a tilemap. With a tilemap, you're doing collision detection against the tiles. Without a tilemap you're doing collision detection against the bounding boxes of individual objects. The logic is almost identical.
Additional info:
I think the problem you're struggling with is that you're thinking in terms of screens. It's important when writing a game to separate the concept of the game world (the model) from the presentation (the screen).
For example, a simple side scroller game might consist of many "screens" full of information. Whereas the screen might be 1000 units wide, the game's world could be 10,000 or 100,000 units wide. Note that I say "units" rather than "pixels". A game's unit of measure could be inches, centimeters, miles, or whatever. All of your game logic should work in terms of world coordinates. How you project that onto the view (the screen) is irrelevant to what goes on in the world.
Every object in the world is assigned a position in world coordinates. That includes the player sprite, which is moving around in the world. All collision detection and other interaction of objects in the world is done in terms of world coordinates.
To simplify things, assume that there is a one-to-one mapping between world units and screen units. That is, your world is 10,000 pixels wide, and your screen is 1,000 pixels wide. The world, then is "ten screens" in size. More correctly, the screen can view 1/10 of the world. If that's the case, then your view can be defined by the left-most world coordinate that's visible. So if the world coordinate 2,000 is at the left of your screen, the rightmost column of pixels on your screen will be world coordinate 2,999.
This implies that you need world-to-screen and screen-to-world transformation functions. For this case, those functions are very simple. If we assume that there's no vertical scrolling, then only the x coordinate needs to be transformed by subtracting the world x coordinate from the view x coordinate. That is, world.x - viewOrigin.x. So in the case above, the screen coordinate of an object that's at world x coordinate 2,315 would be (2,315 - 2,000), or 315. That's the x coordinate of the object's position on the screen. In the current view.
The screen-to-world is the opposite: add the object's screen coordinate to the view's origin: 315 + 2,000 = 2,315.
I can't stress how important it is to maintain this separation between world and view coordinates. All of your game logic should operate in terms of world coordinates. You update the view to show you what's happening in the world. In a side scroller, you typically move the view left and right based on the player's actions. If the player moves left, you move the view origin left. If the player moves right, you move the view origin to the right.
Once you internalize this idea, things become much simpler. Everything done in the game world happens in the world. You make sure that the world state is consistent, and then you worry about displaying a view of the world.
There's no easier way (that I know of) to build a game that's larger than the screen. No matter how you build it, you have to have some concept of showing just part of the world on the view. By formalizing it, you separate the presentation from the game logic and things get much, much simpler.
You are going to want to set you camera dimensions to the dimensions of your level that you want to be rendered. You can get the level coordinates according to whatever you camera is supposed to be fixed on, say your hero.
Sprite collision is relatively easy. Use the two sprites' height/width you're testing against (IDK about cocos2d, but most api's sprites' position are at the upper left corner of the sprite):
if(player.Pos.x <= (object.Pos.x + object.width) || (player.Pos.x + player.width) >= object.Pos.x)
{
if(player.Pos.y >= (object.Pos.y - object.height) || (player.Pos.y - player.height) <= object.Pos.y)
//collision detected
}