How to Project an Image to a Sphere - java

I am trying to get the following image to be projected to a sphere using mercator:
I have gotten this far using the formula from this : how map 2d grid points (x,y) onto sphere as 3d points (x,y,z)
My code is the following to generate the coordinates from (X,Y):
public void generateSphericalCoords(){
int R = 400; // Image Radius
int S = 400; // Sphere Radius
float longitude = (float)(this.x)/R;
float latitude = (float) (2*Math.atan(Math.exp((double)(this.y)/R)) - Math.PI/2);
sphericalX = (int) (S*Math.cos(latitude) * Math.cos(longitude)) + 300;
sphericalY = (int) (S*Math.cos(latitude) * Math.sin(longitude)) + 300;
sphericalZ = (int) (S*Math.sin(longitude));
//System.out.println(sphericalX + " " + sphericalY + " " + sphericalZ);
}
However, instead of getting a perfect sphere, I get this:
What am I doing wrong? Any help would be greatly appreciated.
EDIT:
I have gotten to the following formula:
float longitude = (float) ((float)(Math.PI*this.x)/R - Math.PI/2);
float latitude = (float) (Math.PI*2*Math.atan(Math.exp((float)(this.y)/R)));
sphericalX = (int) (S*Math.cos(latitude) * Math.cos(longitude)) + 300;
sphericalY = (int) (S*Math.cos(latitude) * Math.sin(longitude)) + 300;
sphericalZ = (int) (S*Math.sin(longitude));
However, I have gotten an odd ring along the outside edge, as shown:

Related

how to get the infotmation about the latitude and longitude for the World map image [duplicate]

This question already has answers here:
Convert longitude and latitude coordinates to image of a map pixels X and Y coordinates Java
(2 answers)
Closed 22 days ago.
enter image description herehello all I am trying to find this Number
from this question :
Convert longitude and latitude coordinates to image of a map pixels X and Y coordinates Java
int mapWidth = 614, mapHeight = 1141;
double mapLongitudeStart = 33.5, mapLatitudeStart = 33.5;//longitude vertical, latitude horizontal
// length of map in long/lat
double mapLongitude = 36.5 - mapLongitudeStart,
// invert because it decreases as you go down
mapLatitude = mapLatitudeStart - 29.3;
how can i find this number from the world map image
Try this:
int mapWidth = 614, mapHeight = 1141;
double mapLongitudeWidth = 36.5, mapLatitudeHeight = 29.3;
double mapLongitudeStart = 33.5, mapLatitudeStart = 33.5;//longitude vertical, latitude horizontal
// length of map in long/lat
double mapLongitude = mapLongitudeWidth - mapLongitudeStart;
// invert because it decreases as you go down
double mapLatitude = mapLatitudeStart - mapLatitudeHeight;
int xImagePos = (int) (mapWidth * (mapLongitude/mapLongitudeWidth));
int yImagePos = (int) (mapHeight * (mapLatitude/mapLatitudeHeight));
System.out.println("x: " + xImagePos + ", y: " + yImagePos);
It does seem odd that both mapLongitudeStart and mapLatitudeStart are 33.5. Typo?

Floorcasting not scrolling in raycasting engine?

I'm currently working on a raycaster in Java, and so far, I have the floor correctly textured. The problem, however, is that the floor doesn't scroll. In other words, when I move the camera in the projection, the floor stays the same, yet the walls move as expected. I'm really not sure what I'm doing wrong. I took almost all the code from this reference. Note that I took some liberties when pasting the code in that I used some pseudocode.
I tried applying a player offset to the tileX and tileY variables, e.g., tileX += player.x, and all I got was a floor that scrolls far too quickly and incorrectly.
for every ray:
... // other stuff relating to the walls above here.
int start = (int)(wallY + wallHeight + 1);
double directionCos = cos(rad(ray.getAngle()));
double directionSin = sin(rad(ray.getAngle()));
int textureDim = 16;
for (int y = start; y < screenHeight; y++) {
double distance = screenHeight / (2.f * y - screenHeight);
distance /= cos(rad(player.getAngle()) - rad(ray.getAngle()));
// The source I grabbed the code from actually appends the player's x and y to the tileX and tileY variables, but this completely messes up the textures when I try to.
double tileX = distance * directionCos;
double tileY = distance * directionSin;
int textureX = Math.floorMod((int)(tileX * textureDim), textureDim);
int textureY = Math.floorMod((int)(tileY * textureDim), textureDim);
int rgb = floorTexture.getRGB(textureX, textureY);
projectionFloor.setRGB((int)wallX, y, rgb);
}
Below is an image of the floor.
Below is an animation visualizing the problem.
Below is an animation visualizing what happens if I try to apply a player position offset:
Fixed it on my own. Turns out that, yes, you do have to account for the player's position (shocker!); the source I got the code from just didn't do it correctly.
DTPP = distance to projection plane.
for every pixel y from wallY + wallHeight + 1 to projectionHeight:
double r = y - this.getPreferredSize().height / 2.f;
double d = (CAMERA_HEIGHT * DTPP / r) / ANGLE;
double tileX = CAMERA_X + d * RAY_COSANGLE;
double tileY = CAMERA_Y + d * RAY_SINANGLE;
int textureX = Math.floorMod((int) (tileX * TEXTURE_SIZE /
TEXTURE_SCALE), TEXTURE_SIZE);
int textureY = Math.floorMod((int) (tileY * TEXTURE_SIZE /
TEXTURE_SCALE), TEXTURE_SIZE);
... (drawing occurs here)

strange thing with cylinder algorithm

I want to render a cylinder in Opengl. For that i wrote an simple algorithm, that
generates me the points mesh by the parameters radius, height, xSubDivisions and ySubDivisions:
(Java)
for(int yDivision = 0; yDivision < yDivisionCount; yDivision++){
for(int xDivision = 0; xDivision < xDivisionCount; xDivision++){
float line[] = getVboLine(xDivision, yDivision, radius, height, xDivisionCount, yDivisionCount);
string.append(line[0] + ", " + line[1] + ", " + line[2] + ", " + line[3] + ", " + line[4] + ", ");
}
}
public float[] getVboLine(int xDivision, int yDivision, float radius, float height, int xDivisionCount, int yDivisionCount){
float xDegrees = 360.0f / xDivisionCount * xDivision;
float xRadian = (float) Math.toRadians(xDegrees);
float x = (float) Math.sin(xRadian) * radius;
float z = (float) Math.cos(xRadian) * radius;
float y = (float) yDivision * (height / (yDivisionCount - 1));
float s = xDegrees * (1.0f / 360.0f);
float t = yDivision * (1.0f / (yDivisionCount - 1));
return new float[]{
x, y, z, s, t
};
}
The result is actually an cylinder, (i created an IBO to render this points) but sometimes, with different inputs for x and yDivisions there is a strange gap in it.
I couldn't find a rule, but the values i found this bug with were 200, 100.
To debug i rendered only the points. The result was:
How is this possible? One points is just missing (where i added the reed circle with paint).
Where is the problem with my algorithm?
I am not JAVA coder but you are mixing int and float together
for example:
xDegrees = 360.0f / xDivisionCount * xDivision
[float] [float] [int] [int]
I would rather use this:
xDegrees = float(360*xDivision)/float(xDivisionCount)
multiplication should go always first (if operands are >= 1)
and division after that to preserve accuracy
some weird rounding could cause your problem but it would be more noticeable for lower xDivisionCount not bigger one
Bug breakpoint
add to your code last generated point
after new point computation compute the distance from last point
add if (|distance-some_avg_distance|>1e-10)
and add breakpoint inside
some_avg_distance set by distance that should be there (get it from trace)
this way you can breakpoint the point causing problems (or the next point to it)
so you can actually see what is wrong
my bet is that by rounding you get the same angle as prev/next point
and therefore you do not have missing point but some duplicate instead
you can check that also by Blending

Strange wraping when rotating Bitmaps

I started developing a custom Image class for a game which consists of three basic fields, width, height and a unidimensional array of int's which represent the color in the following order ARGB.
About two days ago i started trying to rotate images, and i was able to do that by converting this to a BufferedImage, rotate using Graphics2D and transforming it back to my own Image class, however setRGB and getRGB seem to be too slow and when i have to rotate about 10-20 images of 64*64 pixels the computer starts to struggle to maintain the fps.
So naturally i started developing my own image rotation function and i found a great post on gamedev.stackexchange.
https://gamedev.stackexchange.com/questions/67613/how-can-i-rotate-a-bitmap-without-d3d-or-opengl
The answer explains clearly what i should do to rotate an image even with different rotation points (which i intend to implement later).
However when following a similar formula to the one he explained (I had to change due to using a different coordinate system)
i find myself getting a strange wrapping at the top
Example (55 degrees): http://i.imgur.com/BBq83wV.png (The Black area represents the image size)
So i tried to distanciate the image from the top, and added
yDstPixel += this.height*sin;
Which sorta worked, but now the image gets clipped in half instead of wrapped
Example (35 degrees):http://i.imgur.com/Ap4aqrn.png
I'm almost sure the solution is very simple, but i cant seem to figure it out, a nudge in the right direction would be appreciated.
public Bitmap getRotatedCopy(double radians){
if(radians==0 || radians==(2*Math.PI)) return this;
double sin = Math.abs(Math.sin(radians));
double cos = Math.abs(Math.cos(radians));
int newWidth = (int) (this.width * cos + this.height * sin);
int newHeight = (int) (this.width * sin + this.height * cos);
Bitmap returnMap = new Bitmap(newWidth,newHeight); //set size of the returned bitmap to the smallest size possible
returnMap.fill(0xFF000000);
for (int y = 0; y < this.height; y++){
for(int x = 0; x < this.width; x++){
int srcPixel = x + (y * this.width);
int color= this.pixels[srcPixel];
if(color>0) continue;
int xDstPixel = (int) Math.abs((x * cos + y * sin));
int yDstPixel = (int) Math.abs((x * sin - y * cos));
//yDstPixel += this.height*sin;
int dstPixel = xDstPixel + (yDstPixel * newWidth);
returnMap.pixels[dstPixel]=color;
}
}
return returnMap;
}
You'll need to implement what you were planning to do later i.e. set the rotation origin and translation after the rotation.
I have modified your code to add them. (I didn't test running it but hope it works.) Please refer to the code below:
int newWidth = (int) (this.width * cos + this.height * sin);
int newHeight = (int) (this.width * sin + this.height * cos);
// After setting the new width and height...
// set rotation origin
double rox = this.width/2;
double roy = this.height/2;
// set translation center
double tcx = newWidth/2;
double tcy = newHeight/2;
Bitmap returnMap = new Bitmap(newWidth,newHeight);
returnMap.fill(0xFF000000);
for (int y = 0; y < this.height; y++){
double yy = y - roy;
for(int x = 0; x < this.width; x++){
double xx = x - rox;
int srcPixel = x + (y * this.width);
int color= this.pixels[srcPixel];
if(color>0) continue;
// following two lines are modified
int xDstPixel = (int) (xx * cos + yy * sin) + tcx;
int yDstPixel = (int) (xx * sin - yy * cos) + tcy;
// prevent negative index : maybe it is not needed at all
if (xDstPixel<0 || yDstPixel<0)
continue;
int dstPixel = xDstPixel + (yDstPixel * newWidth);
returnMap.pixels[dstPixel]=color;
}
}

Java OpenGL: Mouse picking in 3D Space

I am trying to make some sort of 3D Editor with Java and OpenGL. And now I'm implementing the basic functions of an 3D Editor like rotating the camera around a specific Position and zooming. Next I want to do a 3D Picking to select Objects,Lines and Vertices in 3D-Space with the Mouse. I thought this is gonna to be easy because I can already select Objects when the Camera is focusing them.
Here is the example of the Selection of Objects with the Camera focus:
In the Class Camera there is this Method:
public boolean isVecInFocus(Vec3 vec) {
//returns the distance between camera and target
float c = new Vec3(posX,posY,posZ).getDistanceTo(vec);
// returns a Vector by drawing an imiginary line with the length of c and the position and rotation of the camera
Vec3 target = getFocusedPoint(c);
//checks if the calculated Vector is near to the target
if(target.x > vec.x - 0.05f && target.x < vec.x + 0.05f && target.y > vec.y - 0.05f && target.y < vec.y + 0.05f && target.z > vec.z - 0.05f && target.z < vec.z + 0.05f) {
return true;
} else {
return false;
}
}
Now, I want to do the same with the Mouse input:
//Mouse positions
float mX = Mouse.getX();
float mY = Mouse.getY();
//My test Vector
Vec3 vec = new Vec3(-5,5,-8);
//Camera Position
Vec3 camV = new Vec3(cam.getPosX(),cam.getPosY(),cam.getPosZ());
//Distance from Test Vector to Camera
float c = camV.getDistanceTo(vec);
//Calculating of the aspect between width and height (Because fov_x and fov_y are different because of the Screen Resolution, I think)
float aspect = (float) sb.getDisplayWidth() / (float) sb.getDisplayHeight();
//Normal fov refers to fov_y, so here is the fov_x
float fovx = cam.fov * aspect;
//Changing the Rotations to calculate the target Vector with the values of the Mouse position and rotations , not the Camera
float rotY = cam.getRotationY() + (fovx / (float) sb.getDisplayWidth()) * (mX) - (fovx / 2F);
float rotX = cam.getRotationX() + (cam.fov / (float) sb.getDisplayHeight()) * ((float) sb.getDisplayHeight() - mY) - (cam.fov / 2F);
//Calculating the target Vector with simple Math ...
double xDis = c * Math.sin(Math.toRadians(rotY)) * Math.cos(Math.toRadians(rotX));
double yDis = c * Math.sin(Math.toRadians(rotX));
double zDis = c * Math.cos(Math.toRadians(rotY)) * Math.cos(Math.toRadians(rotX));
float posX = (float) (camV.x + xDis);
float posY = (float) (camV.y - yDis);
float posZ = (float) (camV.z - zDis);
Vec3 target = new Vec3(posX,posY,posZ);
//Check if the target Vector and the Test Vector are the same.
If I use this Code, and point with my Mouse at the Test-Vector, the result is not right. The accuracy of the Point gets lower, the bigger the difference between Screen-middle and Mouse position is.
I think it has something to do with the OpenGL Perspective, but I'm not sure ...

Categories