I am trying to write a program in java from scratch that renders a sphere with ray casting technique and phong illumination, but I am a bit lost.
I understand the concept behind the phong equation coefficients, but I don't understand how to get to the vector values, and what is the relation of all this with ray casting
so let's say I want to renders the sphere in the middle of my screen, and I have it's position and radius, so (cx,cy,r). Where exactly do I start now? how exactly do I get to the vector values? my idea is as follows (pseudocode)
int cx = window width/2
int cy = window height/2
int r = 30;
for(i = 0 -> window height) {
for(j = 0 -> window width) {
if( (j-cx)^2 + (i-cy)^2 < r^2) {
//point inside
Color c = phong(arguments..)
draw pixel j,i with color c
}
}
}
but I have no idea if this is correct or not, and if it is, how do I get the vector values, for starters, the Normal?
could you point me in the right way? I have tried googling a lot with no success, thank you in advance
The vectors for calculating the normal usually come from a tessellation (approximation) of the real geometrical object. So you break the sphere up into, say, triangles. Then each triangle (p1,p2,p3) has its own normal vector ((p2-p1)×(p3-p1).
The phong shading method is an interpolation which then (ideally) blurs over the lines that give away the fact that you're drawing triangles instead of a true sphere. It's doesn't help with corners around the sides, though. :(
For the tessellation, one way is to approximate the sphere with Bezier surface patches which can then be subdivided to a suitably small sizes and simplified to triangles. My question over here explores doing this work to draw a teapot (mostly surfaces of revolution, not unlike spheres).
Related
Basically, I have a 3D hexagonal tile map (think something like a simplified Civ 5 map). It is optimized to use a single large mesh to reduce draw calls and easily allow for some cool Civ 5 features (terrain continuity and uv texture bleeding).
I want to support wraparound maps in my game, and so was brainstorming ideas on how to best do this.
For example, if the main camera is approaching the far east of the map, then I can simply perform the translation to the far west by doing:
if(camera.x >= MAP_WIDTH)
camera.translate(0, 0, y);
However, by doing this, there will be a brief timespan in which the player will see the "end" of the board before the translation. I want to eliminate this.
The first idea I had to solve this problem was to basically just modify the above code as follows:
if((camera.x + camera.viewportWidth >= MAP_WIDTH)
camera.translate(0, 0, y);
However, this has the side effect of a "jump" during the translation that feels unnatural.
My final solution, and the subject of the question:
I have three cameras, my main camera, one to the far east, and one to the far west. I basically want to "combine" the matrices of these cameras to render the map outside of its actual bounds.
Basically, if the camera is a certain distance from the world bounds, I want to draw the scene from the other side of the world in the following location. So, for example, this is the pseudo code of what I want to do:
int MAP_WIDTH = 25;
float viewportSize = 10f;
float mainCamX = 24f;
float mainCamY = 15f;
Matrix4 cbnd = camera.combined;
if(camX >= MAP_WIDTH)
camX = 0;
else if(camX < 0)
camX = MAP_WIDTH - camX;
if(camX + viewportSize >= MAP_WIDTH)
cbnd = combineMatrices(mainCam.combined, westCam.combined);
modelBatch.setProjectionMatrix(cbnd);
modelBatch.begin();
//Draw map model
//Draw unit models.
modelBatch.end();
modelBatch.setProjectionMatrix(mainCam.combined);
But I am unsure of how to appropriately combine matrices, and am new to the concept of matrices in general.
Can somebody give me a hand in combining these matrices?
Sounds too complicated. Here is my idea:
I.e. you can display 10x10 fields on screen
you have map 100x100 fields
just increase your map to 110x110 and in that extra space repeat your first (zero-est rows and columns)
that way you can scroll smoothly and when camera reaches i.e. most right position you have on map just return it to 0 X position. Same goes for vertical movement.
So, idea is to have double most left part of map in width of screen width and most top part of map in size of screen height at rigth/bottom of the map respectively.
just trying to paint multiple unfilled triangles rotating a central point in Java. Paint one triangle, rotate the points by a certain radius, and paint another one.
int rad = 10 //Radius between the triangles
int num = 20 //Number of triangles
for (int i = 0; i < num; i++){
// (250,250) would be the center
int[] xPoints = (250,175,325) //X points of the first triangle
int[] yPoints = (250,100,100) //Y points of the first triangle
g.drawPolygon(xPoints,yPoints,3); //Paint the shape
}
Of course my code only prints the first triangle, as I'm unsure how to rotate the points. I've searched around and found some trig, but I don't really understand it. Is there a simple way to rotate each point? Thanks.
Is there a simple way to rotate each point?
Use an AffineTranform that does the geometry for you.
Some examples can be seen in posts tagged affinetransform. Particularly those of mine, Trashgod, MadProgrammer & HovercraftFullOfEels (my apologies if I forgot someone who has done some nice examples).
The Graphics2d object contains an AffineTransform and has a call to set it directly to a rotation about given point.
When using this, you often (not always) want to save a copy of the transform first and then restore it so the next use of g has the original transform rather than a pre- or post-multiplied version:
AffineTransform savedTransform = g.getTransform();
g.rotate(theta, x_center_of_rotation, y_center_of_rotation);
g.setTransform(savedTransform);
Recently, I sought help regarding 3d camera rotations in OpenGL. This answer and the comments that followed helped me greatly, but there is still one major issue: when moving the camera, the motion is often, but not always, in exactly the opposite direction it should be. For instance, when the camera's orientation matrix is the identity, the camera moves perfectly. However, if it is rotated in any direction, its motion on the axis perpendicular to the axis of rotation will have the opposite sign of the intended motion.
With this said, I think I have an idea why this inconsistent behavior is happening:
As we all know, OpenGL uses a Right-Handed coordinate system:
If I understand this diagram correctly, when the camera is oriented at the identity the z axis should point INTO the camera, and z-values should decrease as one moves away from the camera (apparently affirmed here). (coordinates measured in world space).
However, in my program, the Z axis points AWAY from the camera and z values increase as one moves away from the camera. Here is an example:
The camera has moved forward, along what should be the negative z axis but appears to be the positive z axis.
If I am correct in interpreting this behavior as abnormal, it would explain all of my problems with the sign of my camera motion, as the motion that currently appears "correct" would in fact be erroneous and I have consistent signs that I could simply invert to result in correct motion.
So the question is:
Is my Z axis backwards, or is it supposed to be this way?
If it is backwards, why? Judging by multiple discussions on the topic (1, 2, 3), the error is likely to lie where I define my perspective frustum, so I'll put that here:
public static final int P_ZNEAR = 1, P_ZFAR = 500;
public static void perspective()
{
int i = GL11.glGetInteger(GL11.GL_MATRIX_MODE);
GL11.glMatrixMode(GL11.GL_PROJECTION);
GL11.glLoadIdentity();
double ymax, xmax;
ymax = P_ZNEAR * Math.tan(FOV / 2);
xmax = ymax * ASPECT_RATIO;
GL11.glFrustum(xmax, -xmax, -ymax, ymax, P_ZNEAR, P_ZFAR);
GL11.glMatrixMode(i);
}
My maths isn't that good so I'm having a bit of trouble in one of my applications that I'm trying to do where I want a rectangle to represent a vehicle and I want that vehicle/rectangle to "drive" around in a circle. Imagine a roundabout with only 1 vehicle in it, just circling around forever.
If I can get some help how to do that then I'll be able to build on the example and most importantly learn.
If someone could write up a simple example for me I'd be grateful. No background no images, just a rectangle "driving" around in a circle. I'm using java and Swing.
Sorry, I am not sure if could understand clear you exactly need. If you need to draw rectangle which is moving around inside of circle, you can use sin/cos functions.
Something like that:
double r = 50.0; // radius (it might radius of your circle, but consider dimensions of rectangle to make sure you are drawing inside of circle, e.g. circleRadius - rectangeDimesion / 2.0)
for (int f = 0; f < 360; f++) {
double x = Math.sin(Math.toRadians((double)f)) * r;
double y = Math.cos(Math.toRadians((double)f)) * r;
// draw rectangle on [x, y] coordinates
}
If you know the radius of the round about, all the you would need would be a trigonometric function and the angle which the vehicle makes to the round about. You could take a look at this simple introduction which should get you started in the right direction.
On another hand, another approach would be to use a Transformation Matrix where you start with a matrix containing two points (your X and Y co-ordinates) and you transform them to become the new co-ordinates.
You can then rotate the rectangle to mimic a vehicle turning.
If you have a limited background in Mathematics, the first option might be easier for you to grasp.
This is more an extended comment than an answer.
I would divide the problem up into several easier problems, and work on each of them separately:
Draw your rectangle with a specified center location and long axis orientation.
Determine the center point and long axis orientation for an object orbiting around the origin. Note that to get make the long axis a tangent it needs to be perpendicular to the radius through the center.
Translate the whole system so that it orbits the desired point, rather than the origin.
In the context of a Java/OpenGL application I am drawing a black wired only (without filling) big cube composed of 27 smaller cubes. To do that I wrote the following code:
for (int x = 1; x <= 3; x++) {
for (int y = 1; y <= 3; y++) {
for (int z = 1; z <= 3; z++) {
wireCube(x - 2, 2 - y, 2 - z);
}
}
}
The wireCube method is implemented using GL11.glBegin(GL11.GL_LINE_LOOP);
Using the right call to gluPerspective to define the projection and the correct call to gluLookAt to position the "camera" I am able to display my big cube as needed and ....I am very happy with that !!!
My new problem is now, how to modify this code in order to "hide" all the wirings that are inside the big cube ? To help visualize the scene, these wirings are the ones that are usually drawn has dashed lines when learning 3D geometry at school.
Thanks in advance for help
Manu
Enable depth testing (glEnable(GL_DEPTH_TEST)) and put quads on the surfaces of the cubes.
To draw a quad, use glBegin(GL_QUADS) followed by the four vertices and the glEnd() call.
Draw all your cubes with black polygons (or disable color output : glColorMask(false,false,false,false); ): this will fill the depth buffer.
Then draw your lines. The ones hidden by the polygons will not appear. There will be z-fighting though, so glDepthTest(GL_LEQUAL);
If you want to draw "unvisible" lines dashed, this won't be enough. You can draw again with glDepthTest(GL_GREATER);
Another solution is to draw polygons that face the camera with a solid line, and other with a dashed line. This is a simple dot product (camDir.faceNorm).
Use glPolygonOffset() to drown or to emerge your wireframe above (or below) the polygons with the same coordinates.