I try to get started with a 2d map generator with vectors. Now I have some questions how should I go for it.
public float[] gen() {
float[] vec = new float[100];
float x = 0, y = 0;
float a = 20,
b = 10;
for (int i = 0; i < vec.length; i += 2) {
vec[i] = MathUtils.random(x, x + a);
vec[i+1] = MathUtils.random(y - b, y + b);
x = vec[i];
y = vec[i+1];
}
return vec;
}
Would this be a good way to get verctors from? var a, b could be changed for smooth land / hills.
I thought about a neverending map. But how could I only render the part of the player sees. I will work with box2d.
Generated world parts should be saved to a file. Should I save them as chunks like in Minecraft done? And what file fromat is reccoment (json)?
I just liked to get a little perpective to look forwart.
Answer for 2nd Q.
You have to have a Camera
if(x >=camera.project(new Vector3(camera.position.x - camera.viewportWidth - 25, 0, 0)).x) && x <= camera.project(new Vector3(camera.viewportWidth + camera.position.x + 25, 0, 0)).x)
and y the same or less laggy than this(every frame there is created new Vector3 object, so...)
Good luck!
Related
(please don't mark this question as not clear, I spent a lot of time posting it ;) )
Okay, I am trying to make a simple 2d java game engine as a learning project, and part of it is rendering a filled polygon as a feature.
I am creating this algorithm my self, and I really can't figure out what I am doing wrong.
My though process is something like so:
Loop through every line, get the number of points in that line, then get the X location of every point in that line,
Then loop through the line again this time checking if the x in the loop is inside one of the lines in the points array, if so, draw it.
Disclaimer: the Polygon class is another type of mesh, and its draw method returns an int array with lines drawn through each vertex.
Disclaimer 2: I've tried other people's solutions but none really helped me and none really explained it properly (which is not the point in a learning project).
The draw methods are called one per frame.
FilledPolygon:
#Override
public int[] draw() {
int[] pixels = new Polygon(verts).draw();
int[] filled = new int[width * height];
for (int y = 0; y < height; y++) {
int count = 0;
for (int x = 0; x < width; x++) {
if (pixels[x + y * width] == 0xffffffff) {
count++;
}
}
int[] points = new int[count];
int current = 0;
for (int x = 0; x < width; x++) {
if (pixels[x + y * width] == 0xffffffff) {
points[current] = x;
current++;
}
}
if (count >= 2) {
int num = count;
if (count % 2 != 0)
num--;
for (int i = 0; i < num; i += 2) {
for (int x = points[i]; x < points[i+1]; x++) {
filled[x + y * width] = 0xffffffff;
}
}
}
}
return filled;
}
The Polygon class simply uses Bresenham's line algorithm and has nothing to do with the problem.
The game class:
#Override
public void load() {
obj = new EngineObject();
obj.addComponent(new MeshRenderer(new FilledPolygon(new int[][] {
{0,0},
{60, 0},
{0, 60},
{80, 50}
})));
((MeshRenderer)(obj.getComponent(MeshRenderer.class))).color = CYAN;
obj.transform.position.Y = 100;
}
The expected result is to get this shape filled up.(it was created using the polygon mesh):
The actual result of using the FilledPolygon mesh:
You code seems to have several problems and I will not focus on that.
Your approach based on drawing the outline then filling the "inside" runs cannot work in the general case because the outlines join at the vertices and intersections, and the alternation outside-edge-inside-edge-outside is broken, in an unrecoverable way (you can't know which segment to fill by just looking at a row).
You'd better use a standard polygon filling algorithm. You will find many descriptions on the Web.
For a simple but somewhat inefficient solution, work as follows:
process all lines between the minimum and maximum ordinates; let Y be the current ordinate;
loop on the edges;
assign every vertex a positive or negative sign if y ≥ Y or y < Y (mind the asymmetry !);
whenever the endpoints of an edge have a different sign, compute the intersection between the edge and the line;
you will get an even number of intersections; sort them horizontally;
draw between every other point.
You can get a more efficient solution by keeping a trace of which edges cross the current line, in a so-called "active list". Check the algorithms known as "scanline fill".
Note that you imply that pixels[] has the same width*height size as filled[]. Based on the mangled output, I would say that they are just not the same.
Otherwise if you just want to fill a scanline (assuming everything is convex), that code is overcomplicated, simply look for the endpoints and loop between them:
public int[] draw() {
int[] pixels = new Polygon(verts).draw();
int[] filled = new int[width * height];
for (int y = 0; y < height; y++) {
int left = -1;
for (int x = 0; x < width; x++) {
if (pixels[x + y * width] == 0xffffffff) {
left = x;
break;
}
}
if (left >= 0) {
int right = left;
for (int x = width - 1; x > left; x--) {
if (pixels[x + y * width] == 0xffffffff) {
right = x;
break;
}
}
for (int x = left; x <= right; x++) {
filled[x + y * width] = 0xffffffff;
}
}
}
return filled;
}
However this kind of approach relies on having the entire polygon in the view, which may not always be the case in real life.
I am doing this in processing which is essentially java and I have never attempted anything like this before. Can't find any examples of collision detection using arrays to map the pixels.
I am not really trying to make them realistic collisions. I was thinking it would have the same response as if it hit a wall which is just for it to change directions in whatever axis is appropriate for the wall it hit.
I have tried checking if the x and y position are the same but can't seem to make that work. I'd appreciate any input on this.
import java.util.Arrays;
int numOfParticles = 10;
float[] x = new float[numOfParticles]; //initial position of y only matters
float[] px = new float[numOfParticles];
float[] y = new float[numOfParticles];
float[] py = new float[numOfParticles];
int speed = 10;//inversly related to speed
float[] xIncrement = new float[numOfParticles]; //the ratio of increments determines the pattern
float[] yIncrement = new float[numOfParticles]; // it is the slope of the line
//float xIncrement = 10/speed; //the ratio of increments determines the pattern
//float yIncrement = 11/speed; // it is the slope of the line
color currentColor;
int alpha = 100;//range of 0-255
//radius of ball
int radius = 1;
//thickness of line behind ball
int thickness = 5;
int rateOfColor = 5; //this is inversely related to rate but also changes the range of colors
int maxColor = 255;
int minColor = 0;
void setup(){
size(500,500);
background(0);
colorMode(HSB);
strokeWeight(thickness);
frameRate(60);
//initialize particles
for(int i = 0;i<numOfParticles;i++){
xIncrement[i] = random(0,100)/speed; //the ratio of increments determines the pattern
yIncrement[i] = random(0,100)/speed; // it is the slope of the line
x[i] = random(0,width);
px[i] = x[i];
y[i] = random(0,height);
py[i] = y[i];
}
//you can either initialize all of them individually or do a random one
//x[0] = 0;
//px[0] = x[0];
//y[0] = 450;
//py[0] = y[0];
//x[1] = width;
//px[1] = x[1];
//y[1] = 450;
//py[1] = y[1];
}
void draw(){
background(0); //comment out for criss cross
for(int i = 0; i < numOfParticles; i++){
particle(i);
}
}
void particle(int particleNum){
currentColor = color(minColor + (x[particleNum]/rateOfColor)%maxColor,255,255,alpha);
stroke(currentColor);
fill(currentColor);
ellipse(x[particleNum],y[particleNum],radius,radius);
line(px[particleNum],py[particleNum],x[particleNum],y[particleNum]);
px[particleNum] = x[particleNum];
py[particleNum] = y[particleNum];
y[particleNum]+= yIncrement[particleNum];
x[particleNum]+= xIncrement[particleNum];
if(x[particleNum] > width + 1 || x[particleNum] < 0){
x[particleNum] -= 2*xIncrement[particleNum];
xIncrement[particleNum]*=-1;
}
if( y[particleNum] > height + 1 || y[particleNum] < 0){
y[particleNum] -= 2*yIncrement[particleNum];
yIncrement[particleNum]*=-1;
}
//if(Arrays.binarySearch(x,x[particleNum]) >= 0 && Arrays.binarySearch(y,y[particleNum]) >= 0){
// xIncrement[particleNum]*=-1;
// yIncrement[particleNum]*=-1;
// print("*\n");
// stop();
//}
print("x[0] = " + x[0] + "\n");
print("x[1] = " + x[1] + "\n");
print("y[0] = " + y[0] + "\n");
print("y[1] = " + y[1] + "\n");
}
Stack Overflow isn't really designed for general "how do I do this" type questions. It's for specific "I tried X, expected Y, but got Z instead" type questions. But I'll try to help in a general sense:
You need to break your problem down into smaller pieces and then take those pieces on one at a time. Don't worry about the whole particle system. Make it work for a single particle. Do some research on collision detection.
Then if you get stuck, you can post a more specific question along with a MCVE. Good luck.
Ptoject Tango provides a point cloud, how can you get the position in pixels of a 3D point in the point cloud in meters?
I tried using the projection matrix but I get very small values (0.5,1.3 etc) instead of say 1234,324 (in pixels).
I include the code I have tried
//Get the current rotation matrix
Matrix4 projMatrix = mRenderer.getCurrentCamera().getProjectionMatrix();
//Get all the points in the pointcloud and store them as 3D points
FloatBuffer pointsBuffer = mPointCloudManager.updateAndGetLatestPointCloudRenderBuffer().floatBuffer;
Vector3[] points3D = new Vector3[pointsBuffer.capacity()/3];
int j =0;
for (int i = 0; i < pointsBuffer.capacity() - 3; i = i + 3) {
points3D[j]= new Vector3(
pointsBuffer.get(i),
pointsBuffer.get(i+1),
pointsBuffer.get(i+2));
//Log.v("Points3d", "J: "+ j + " X: " +points3D[j].x + "\tY: "+ points3D[j].y +"\tZ: "+ points3D[j].z );
j++;
}
//Get the projection of the points in the screen.
Vector3[] points2D = new Vector3[points3D.length];
for(int i =0; i < points3D.length-1;i++)
{
Log.v("Points", "X: " +points3D[i].x + "\tY: "+ points3D[i].y +"\tZ: "+ points3D[i].z );
points2D[i] = points3D[i].multiply(projMatrix);
Log.v("Points", "pX: " +points2D[i].x + "\tpY: "+ points2D[i].y +"\tpZ: "+ points2D[i].z );
}
The example I'm using is the point cloud java which can be found here
https://github.com/googlesamples/tango-examples-java
UPDATE
TangoCameraIntrinsics ccIntrinsics = mTango.getCameraIntrinsics(TangoCameraIntrinsics.TANGO_CAMERA_COLOR);
double fx = ccIntrinsics.fx;
double fy = ccIntrinsics.fy;
double cx = ccIntrinsics.cx;
double cy = ccIntrinsics.cy;
double[][] projMatrix = new double[][] {
{fx, 0 , -cx},
{0, fy, -cy},
{0, 0, 1}
};
Then to compute the projected point I use
for(int i =0; i < points3D.length-1;i++)
{
double[][] point = new double[][] {
{points3D[i].x},
{points3D[i].y},
{points3D[i].z}
};
double [][] point2d = CustomMatrix.multiplyByMatrix(projMatrix, point);
points2D[i] = new Vector2(0,0);
if(point2d[2][0]!=0)
{
Log.v("temp point", "pX: " +point2d[0][0]/point2d[2][0]+" pY: " +point2d[1][0]/point2d[2][0] );
points2D[i] = new Vector2(point2d[0][0]/point2d[2][0],point2d[1][0]/point2d[2][0]);
}
}
But I think that the results are still not what is expected, I for instance get results like:
pX: -175.58042313027244 pY: -92.573740812066
Which to me looks not right.
UPDATE
Using color camera as suggested gives better results, but poitns are still negative
-1127.8086915171814 pY: -652.5887102192332
Would it be ok to just multiply them by -1?
You have to multiply 3D point with RGB camera's intrinsics matrix to obtain pixel coordinate. 3D points are in Depthcamera's frame. You get pixel coordinates by following method:
and
x and y are pixel coordinates.
And K is constructed with parameters using intrinsics function
So I want to create array [64][64] of 0 in java and create triangle of ones here. I mean something like:
0001000
0010100
0100010
1111111
So I created class point:
public class Point {
public int x;
public int y;
Point(int x, int y)
{
this.x = x;
this.y = y;
}
}
And I'm creating in main new points objects in that way:
int amountOfPowers = 6;
Point a = new Point((int) (Math.pow(2, amountOfPowers))/2, 0);
Point b = new Point((int) Math.pow(2, amountOfPowers), (int) (Math.pow(2, amountOfPowers) * Math.sqrt(3.0) / 2));
Point c = new Point(0, (int) (Math.pow(2, amountOfPowers) * Math.sqrt(3.0) / 2));
So A is (0, 64), B is (64, 64) and C is (32, 55). Somebody has any idea how can I write all positions in array from 0,64 to 64,64 as 1? (something like [0][64] = 1, [1][64] = 1, ..., [64][64] = 1).
And also how can I create lines of ones from (0,64) to (32, 55) and from (32, 55) to (64, 64). Somebody have any idea how can I do this?
#edit
I tried to use it:
https://en.wikipedia.org/wiki/Line_drawing_algorithm
Here is my method:
static void drawLine(Point from, Point to) {
// https://en.wikipedia.org/wiki/Line_drawing_algorithm
int dx = to.x - from.x;
int dy = to.y - from.y;
for (int x = from.x; x < to.x; x++) {
int y = from.y + dx * (x - from.x) / dy;
System.out.println("X: " + x + " Y: " + y);
canvas[x][y] = 1;
}
}
I wrote this in main:
drawLine(a, b);
drawLine(b, c);
drawLine(c, a);
And here is my result :/ It's something wrong.
0000000000000000000000000000000000000000000000000000000100000000
0000000000000000000000000000000000000000000000000000000100000000
0000000000000000000000000000000000000000000000000000001000000000
0000000000000000000000000000000000000000000000000000001000000000
0000000000000000000000000000000000000000000000000000010000000000
0000000000000000000000000000000000000000000000000000010000000000
0000000000000000000000000000000000000000000000000000100000000000
0000000000000000000000000000000000000000000000000001000000000000
0000000000000000000000000000000000000000000000000001000000000000
0000000000000000000000000000000000000000000000000010000000000000
0000000000000000000000000000000000000000000000000010000000000000
0000000000000000000000000000000000000000000000000100000000000000
0000000000000000000000000000000000000000000000000100000000000000
0000000000000000000000000000000000000000000000001000000000000000
0000000000000000000000000000000000000000000000010000000000000000
0000000000000000000000000000000000000000000000010000000000000000
0000000000000000000000000000000000000000000000100000000000000000
0000000000000000000000000000000000000000000000100000000000000000
0000000000000000000000000000000000000000000001000000000000000000
0000000000000000000000000000000000000000000010000000000000000000
0000000000000000000000000000000000000000000010000000000000000000
0000000000000000000000000000000000000000000100000000000000000000
0000000000000000000000000000000000000000000100000000000000000000
0000000000000000000000000000000000000000001000000000000000000000
0000000000000000000000000000000000000000001000000000000000000000
0000000000000000000000000000000000000000010000000000000000000000
0000000000000000000000000000000000000000100000000000000000000000
0000000000000000000000000000000000000000100000000000000000000000
0000000000000000000000000000000000000001000000000000000000000000
0000000000000000000000000000000000000001000000000000000000000000
0000000000000000000000000000000000000010000000000000000000000000
0000000000000000000000000000000000000100000000000000000000000000
1000000000000000000000000000000000000000000000000000000000000000
1000000000000000000000000000000000000000000000000000000000000000
0100000000000000000000000000000000000000000000000000000000000000
0100000000000000000000000000000000000000000000000000000000000000
0010000000000000000000000000000000000000000000000000000000000000
0010000000000000000000000000000000000000000000000000000000000000
0001000000000000000000000000000000000000000000000000000000000000
0000100000000000000000000000000000000000000000000000000000000000
0000100000000000000000000000000000000000000000000000000000000000
0000010000000000000000000000000000000000000000000000000000000000
0000010000000000000000000000000000000000000000000000000000000000
0000001000000000000000000000000000000000000000000000000000000000
0000001000000000000000000000000000000000000000000000000000000000
0000000100000000000000000000000000000000000000000000000000000000
0000000010000000000000000000000000000000000000000000000000000000
0000000010000000000000000000000000000000000000000000000000000000
0000000001000000000000000000000000000000000000000000000000000000
0000000001000000000000000000000000000000000000000000000000000000
0000000000100000000000000000000000000000000000000000000000000000
0000000000010000000000000000000000000000000000000000000000000000
0000000000010000000000000000000000000000000000000000000000000000
0000000000001000000000000000000000000000000000000000000000000000
0000000000001000000000000000000000000000000000000000000000000000
0000000000000100000000000000000000000000000000000000000000000000
0000000000000100000000000000000000000000000000000000000000000000
0000000000000010000000000000000000000000000000000000000000000000
0000000000000001000000000000000000000000000000000000000000000000
0000000000000001000000000000000000000000000000000000000000000000
0000000000000000100000000000000000000000000000000000000000000000
0000000000000000100000000000000000000000000000000000000000000000
0000000000000000010000000000000000000000000000000000000000000000
0000000000000000001000000000000000000000000000000000000000000000
Anybody have idea how can I solve my problem? :/
If you will think about your arrays as a screen and about 1's as dark pixels and zeroes as white pixels than you have task of drawing a line on screen. In reality it is exactly the task that being actively performed in video card.
Algorithm is expressed here https://en.wikipedia.org/wiki/Line_drawing_algorithm
NB: in algorithm they use int's and due rounding issues you might be will have better results if you will swap coords and will iterate using y instead of x.
i really need your help since that i am fighting with the unknown for some time now.
I am trying to draw a parametric surface on java 3d. The surface is being drawn if i a use a point array. Here is the code :
PointArray lsa=new PointArray(length, GeometryArray.COLOR_3|GeometryArray.NORMALS|GeometryArray.COORDINATES);
float maxV=(float) ((float) 2*Math.PI);
float maxU=(float) ((float) Math.PI);
Vector3f norm = new Vector3f();
for (float v = 0.01f; v < maxV; v+=0.03)
{
for (float u = 0.01f; u < maxU; u+=0.03)
{
vIndex++;
Point3f pt = new Point3f();
pt.x=(float) (Math.sin(u)*Math.cos(v));
pt.y=(float) (2*Math.sin(u)*Math.sin(v));
pt.z=(float) Math.cos(u);
lsa.setCoordinate(vIndex, pt);
lsa.setColor(vIndex, new Color3f(0.9f,0.0f,0.0f));
}
}
Shape3D shape = new Shape3D(lsa);
The problem that I have is that it's drawing only the points (dots) so it's not a full drawn surface. How can I draw this parametric surface with polygons or any surface? Are there any methods ?
I am searching the Web, bought Books but I still can not make it with java 3d.
Thank you very much.
Here's how I would do it.
I would define a
Point3f[][] points = new Point3f[(int)((umax-umin)/du)][(int)((vmax-vmin)/dv)];
Then use loops similar to the ones you have int i = 0; i<points.length; i++, int j = 0; j < points[0].length; j++. Define u = i * du + umin, v = j * dv + vmin.
and populate this array with Point3f corresponding to (u, v).
Loop int i = 0; i<points.length - 1; i++, int j = 0; j < points[0].length - 1; j++ and get the points at points[i][j], points[i+1][j], points[i][j+1], and points[i+1][j+1].
Then use the method given in this article to convert these points into a Polygon. Add it to your model / an array that you later add to your model.
Of course, this may not be the best way to do it and I have the feeling that it doesn't handle discontinuities very well, but it should at least make polygons.
Hello here is the solution, it draws a coons surface for example, it should work for any parametric surface x(s, t), y(s, t), z(s, t).
public static Shape3D getShape3D()
{
//Coons
int ns=100;
int nt=100;
float param0=1.0f;
float param1=3.0f;
float s=0.0f;
float t=0.0f;
if (ns>500) ns=500;
if (nt>500) nt=500;
Point3f[][] f=new Point3f[ns][nt];
int sizeOfVectors=0;
for (int i=0;i<ns;i++) //t -->s
{
for (int j=0;j<nt;j++) //u ---t
{
s=((float) i/ns);
t=((float) j/nt);
//System.out.println(" i "+ i + " j "+ j + " s "+ s + " t "+ t);
f[i][j]=new Point3f();
//f[i][j].x=s;
//f[i][j].y=2*t;
//f[i][j].z=10*t*(1-s);
f[i][j].x=param0*s;
f[i][j].y=param1*t;
f[i][j].z=(float) (0.5*((54*s*Math.sqrt(s)-126*Math.sqrt(s)+72*s-6)*t+(27*Math.sqrt(s)-27*s+6)));
/*f[i][j].x = (float) (Math.sqrt(s)*Math.cos(t));
f[i][j].y=(float) (Math.sqrt(s)*Math.sin(t));
f[i][j].z=s;*/
sizeOfVectors++;
sizeOfVectors++;
}
}
System.out.println("Total vectors "+sizeOfVectors);
Shape3D plShape = new Shape3D();
int vIndex=-1;
int k=0;
for (int i=0;i<(ns-1);i++)
{
k=i+1;
sizeOfVectors=nt*2;
vIndex=-1;
TriangleStripArray lsa=new TriangleStripArray(sizeOfVectors, GeometryArray.COLOR_3|GeometryArray.COORDINATES|GeometryArray.NORMALS, new int[] {sizeOfVectors});
for (int j=0;j<nt;j++)
{
vIndex++;
lsa.setCoordinate(vIndex, f[i][j]);
lsa.setColor(vIndex, new Color3f(0.9f,0.0f,0.0f));
vIndex++;
lsa.setCoordinate(vIndex, f[k][j]);
lsa.setColor(vIndex, new Color3f(0.9f,0.0f,0.0f));
}
plShape.addGeometry(lsa);
}
return plShape;
}
It works like a dream. Your guidance was the catalyst to finally make it.