• Advertisement
  • Popular Tags

  • Popular Now

  • Advertisement
  • Similar Content

    • By akshayMore
      Hello,
      I am trying to make a GeometryUtil class that has methods to draw point,line ,polygon etc. I am trying to make a method to draw circle.  
      There are many ways to draw a circle.  I have found two ways, 
      The one way:
      public static void drawBresenhamCircle(PolygonSpriteBatch batch, int centerX, int centerY, int radius, ColorRGBA color) { int x = 0, y = radius; int d = 3 - 2 * radius; while (y >= x) { drawCirclePoints(batch, centerX, centerY, x, y, color); if (d <= 0) { d = d + 4 * x + 6; } else { y--; d = d + 4 * (x - y) + 10; } x++; //drawCirclePoints(batch,centerX,centerY,x,y,color); } } private static void drawCirclePoints(PolygonSpriteBatch batch, int centerX, int centerY, int x, int y, ColorRGBA color) { drawPoint(batch, centerX + x, centerY + y, color); drawPoint(batch, centerX - x, centerY + y, color); drawPoint(batch, centerX + x, centerY - y, color); drawPoint(batch, centerX - x, centerY - y, color); drawPoint(batch, centerX + y, centerY + x, color); drawPoint(batch, centerX - y, centerY + x, color); drawPoint(batch, centerX + y, centerY - x, color); drawPoint(batch, centerX - y, centerY - x, color); } The other way:
      public static void drawCircle(PolygonSpriteBatch target, Vector2 center, float radius, int lineWidth, int segments, int tintColorR, int tintColorG, int tintColorB, int tintColorA) { Vector2[] vertices = new Vector2[segments]; double increment = Math.PI * 2.0 / segments; double theta = 0.0; for (int i = 0; i < segments; i++) { vertices[i] = new Vector2((float) Math.cos(theta) * radius + center.x, (float) Math.sin(theta) * radius + center.y); theta += increment; } drawPolygon(target, vertices, lineWidth, segments, tintColorR, tintColorG, tintColorB, tintColorA); } In the render loop:
      polygonSpriteBatch.begin(); Bitmap.drawBresenhamCircle(polygonSpriteBatch,500,300,200,ColorRGBA.Blue); Bitmap.drawCircle(polygonSpriteBatch,new Vector2(500,300),200,5,50,255,0,0,255); polygonSpriteBatch.end(); I am trying to choose one of them. So I thought that I should go with the one that does not involve heavy calculations and is efficient and faster.  It is said that the use of floating point numbers , trigonometric operations etc. slows down things a bit.  What do you think would be the best method to use?  When I compared the code by observing the time taken by the flow from start of the method to the end, it shows that the second one is faster. (I think I am doing something wrong here ).
      Please help!  
      Thank you.  
    • By menyo
      I have a MongoDB db on a server operated by Kryonet. Obviously I need to be able to query the database from the client for adding, removing, requesting all kind of assets. Now I have written the code to request, add and remove fighters on the Kryonet network I am wondering if there is a better way to do this. I feel it's a bit repetitive, especially when I need to implement this for all other assets the player can own and other players assets when needed. The way I am currently approaching this is the same as my chat/lobby system which works great but I was wondering if anyone could see improvement on my code or a complete different way that is much more scalable perhaps.
       
      public class ClientAssets { public static final int FIGHTER_REQUEST = 1; public static final int FIGHTER_RESPONSE = 2; public static final int FIGHTER_ADD = 3; public static final int FIGHTER_REMOVE = 4; public static void Register(EndPoint endPoint) { Kryo kryo = endPoint.getKryo(); kryo.register(FighterRequest.class); kryo.register(FighterResponse.class); kryo.register(FighterAdd.class); kryo.register(FighterRemove.class); } static public abstract class AssetPacket { public int packetId; public AssetPacket() { } } /** * Packet to request all owned fighters */ public static class FighterRequest extends AssetPacket { public ObjectId playerId; public FighterRequest(ObjectId playerId) { packetId = FIGHTER_REQUEST; this.playerId = playerId; } public FighterRequest() { } } /** * Receiving fighter data from server */ public static class FighterResponse extends AssetPacket { public Fighter fighter; public boolean add; // Add or remove public FighterResponse(Fighter fighter, boolean add) { packetId = FIGHTER_RESPONSE; this.fighter = fighter; this.add = add; } public FighterResponse() { } } /** * Adds a fighter to player assets */ public static class FighterAdd extends AssetPacket { public ObjectId fighterTemplateID; public FighterAdd(ObjectId fighterTemplateID) { packetId = FIGHTER_ADD; this.fighterTemplateID = fighterTemplateID; } public FighterAdd() { } } /** * Removes fighter from assets. */ public static class FighterRemove extends AssetPacket { public ObjectId fighterId; public FighterRemove(ObjectId fighterId) { packetId = FIGHTER_REMOVE; this.fighterId = fighterId; } public FighterRemove() { } } } To elaborate a bit more, this code will communicate between client and server. When receiving a request on the server it will lookup the request in the database. The client will store it for displaying the assets. A specific thing I am unsure about is the FighterResponse.add boolean. I need to be able to remove and add fighters, I guess I am better off with a FighterAddResponse and a FighterRemove response so I will send one boolean less each time this packet is send. But this will create even more repetitive code.
    • By Sparsh Tyagi
      I recently released my first puzzle game for Android which is called here.
      It's a simple looking game which has 50 unique levels. Each level has its own logic and you have to find/make the word here in each level. There are also 3 hints per level just in case you get stuck.

      I have never made videos in my life before but here's a quick look at the game:
      The reviews so far have been great and now I wish to share it with you guys.
      I would love to have any feedback or suggestions or criticism. It will help a lot!

      Link: https://play.google.com/store/apps/details?id=com.techyonic.here

      Thank you!
       




    • By Alexander Winter
       
          Jumpaï is a game about creating platformer levels and playing them online with everyone. Will you become the most popular level maker or will you be a speedrunner holding world records on everyone's levels? More into casual play? No problem! You can happily play through the giant level database or chill at people's hub. Meet new people, make new friends, learn to master the game by asking pros or ask for people's favorite tricks on level making. Download here: https://jumpai.itch.io/jumpa Discord: https://discord.gg/dwRTNCG   Trailer:      (The following screenshots are older but still a bit representative)  





      Unlike other games of its genre, Jumpaï is about playing levels with everyone in real time. You have the fun to see how other people are playing and get to realize you are not the only one failing that jump!

      The game is currently into development and still have lots to do. I am looking for people willing to help how they can. Developer? Graphist? Play tester? Sound designer? Game designer? I'm welcoming everyone. The project is so big I have a lot of work to do in all areas. Server backend, UI/UX, Game networking, Gameplay and even the website some day. As you can see from the default buttons, the game has been made with LibGDX. Update 2018-03-31: Still taking all kind of talents but we are in great need of graphists.

      If you plan to take an important role into the development of the game, we will discuss how you will get paid once the game generates money. Note that I'm not working on the game full-time. I'm studying full-time and working on it is a hobby. It's been 16 months since it started.

      So, are you interested? If so join me on my discord https://discord.gg/dwRTNCG and I'll answer all your questions.

      Additionnal screenshots:
       



       
  • Advertisement
  • Advertisement

Recommended Posts

Posted (edited)

Hey guys, I've been working on some marching cubes, and I've been having some weird issues that I really can't seem to understand. Basically the mesh isn't forming properly. Here are some screenshots and the code as it will show you the issue quicker than me describing it.

3yDmnZ9.pngtY5ZubD.pngwAQe0fH.png

 

As you can see the cube kinda forms but some areas are messed up, Here is the relevant code.

 

package voxels;

import java.util.ArrayList;
import java.util.List;

import javax.swing.plaf.basic.BasicTreeUI.TreeCancelEditingAction;

import org.lwjgl.util.vector.Vector3f;
import models.MarchingCubesCases;
import toolbox.UniversalFunctions;

public class MeshGenerator {

	private static int[][] vertexOffset = new int[][] { { 0, 0, 0 }, { 1, 0, 0 }, { 1, 1, 0 }, { 0, 1, 0 }, { 0, 0, 1 },
			{ 1, 0, 1 }, { 1, 1, 1 }, { 0, 1, 1 } };
	private static float target = 0.5f;

	public static Voxel[][][] generateVoxels(int size) {
		Voxel[][][] voxels = new Voxel[size][size][size];

		for (int i = 0; i < size; i++) {
			for (int j = 0; j < size; j++) {
				for (int k = 0; k < size; k++) {
					voxels[i][j][k] = new Voxel(VoxelMaterial.Grass);
				}
			}
		}

		return voxels;
	}

	public static MeshData generateMeshMarchingCubes(Voxel[][][] voxels) {

		List<Vector3f> verts = new ArrayList<Vector3f>();
		List<Float> normals = new ArrayList<Float>();
		List<Integer> indices = new ArrayList<Integer>();
		List<Float> textureCoords = new ArrayList<Float>();

		for (int x = 0; x < voxels.length; x++) {
			for (int y = 0; y < voxels.length; y++) {
				for (int z = 0; z < voxels.length; z++) {

					if (voxels[x][y][z].getMaterial() == VoxelMaterial.Air) {
						continue;
					}

					float[] cube = new float[8];

					if (checkIfExpose(voxels, x, y, z, cube) == false) {
						continue;
					}

					MarchCube(new Vector3f(x, y, z), cube, verts, indices);

					normals.add(0f);
					normals.add(1f);
					normals.add(0f);

					textureCoords.add(0f);
					textureCoords.add(1f);
				}
			}
		}

		MeshData data = new MeshData();
		data.setIndices(UniversalFunctions.intListToArray(indices));
		data.setVertsFromVector3f(verts);
		data.setNormals(UniversalFunctions.floatListToArray(normals));
		data.setTextureCoords(UniversalFunctions.floatListToArray(textureCoords));

		return data;
	}
	
	private static boolean checkIfExpose(Voxel[][][] voxels, int x, int y, int z, float[] cube) {

		Voxel[] surroundingVoxels = getSurroundingVoxels(voxels, x, y, z);
		boolean bool = false;

		for (int i = 0; i < cube.length; i++) {
			cube[i] = 1;
		}

		if (surroundingVoxels[0].getMaterial().equals(VoxelMaterial.Air)) {

			cube[0] = 0;
			cube[1] = 0;
			cube[4] = 0;
			cube[5] = 0;
			bool = true;

		}

		if (surroundingVoxels[1].getMaterial().equals(VoxelMaterial.Air)) {

			cube[0] = 0;
			cube[3] = 0;
			cube[4] = 0;
			cube[7] = 0;
			bool = true;

		}

		if (surroundingVoxels[2].getMaterial().equals(VoxelMaterial.Air)) {

			cube[4] = 0;
			cube[5] = 0;
			cube[6] = 0;
			cube[7] = 0;
			bool = true;

		}

		if (surroundingVoxels[3].getMaterial().equals(VoxelMaterial.Air)) {

			cube[0] = 0;
			cube[1] = 0;
			cube[2] = 0;
			cube[3] = 0;
			bool = true;

		}

		if (surroundingVoxels[4].getMaterial().equals(VoxelMaterial.Air)) {

			cube[1] = 0;
			cube[2] = 0;
			cube[5] = 0;
			cube[6] = 0;
			bool = true;

		}

		if (surroundingVoxels[5].getMaterial().equals(VoxelMaterial.Air)) {

			cube[2] = 0;
			cube[3] = 0;
			cube[6] = 0;
			cube[7] = 0;
			bool = true;

		}

		return bool;
	}

	private static Voxel[] getSurroundingVoxels(Voxel[][][] voxels, int x, int y, int z) {

		int maxLength = voxels.length;
		List<Voxel> voxelList = new ArrayList<Voxel>();

		if (y - 1 > 0 && y - 1 < maxLength) {
			voxelList.add(voxels[x][y - 1][z]);
		} else {
			voxelList.add(new Voxel(VoxelMaterial.Air));
		}

		if (x - 1 > 0 && x - 1 < maxLength) {
			voxelList.add(voxels[x - 1][y][z]);
		} else {
			voxelList.add(new Voxel(VoxelMaterial.Air));
		}

		if (z - 1 > 0 && z - 1 < maxLength) {
			voxelList.add(voxels[x][y][z - 1]);
		} else {
			voxelList.add(new Voxel(VoxelMaterial.Air));
		}

		if (z + 1 > 0 && z + 1 < maxLength) {
			voxelList.add(voxels[x][y][z + 1]);
		} else {
			voxelList.add(new Voxel(VoxelMaterial.Air));
		}

		if (x + 1 > 0 && x + 1 < maxLength) {
			voxelList.add(voxels[x + 1][y][z]);
		} else {
			voxelList.add(new Voxel(VoxelMaterial.Air));
		}

		if (y + 1 > 0 && y + 1 < maxLength) {
			voxelList.add(voxels[x][y + 1][z]);
		} else {
			voxelList.add(new Voxel(VoxelMaterial.Air));
		}

		return voxelList.toArray(new Voxel[voxelList.size()]);
	}

	// MarchCube performs the Marching Cubes algorithm on a single cube
	private static void MarchCube(Vector3f pos, float[] cube, List<Vector3f> vertList, List<Integer> indexList) {
		int i, j, vert, idx;
		int flagIndex = 0;
		float offset = 0.0f;

		Vector3f[] edgeVertex = new Vector3f[12];

		for (int inter = 0; inter < 12; inter++) {
			edgeVertex[inter] = new Vector3f();
		}

		// Find which vertices are inside of the surface and which are outside
		for (i = 0; i < 8; i++) {
			if (cube[i] <= target) {
				flagIndex |= 1 << i;
			}
		}

		// Find which edges are intersected by the surface
		int edgeFlags = MarchingCubesCases.cubeEdgeFlags[flagIndex];

		// If the cube is entirely inside or outside of the surface, then there will be
		// no intersections
		if (edgeFlags == 0)
			return;

		// Find the point of intersection of the surface with each edge
		for (i = 0; i < 12; i++) {

			// if there is an intersection on this edge
			if ((edgeFlags & (1 << i)) != 0) {
				offset = GetOffset(cube[MarchingCubesCases.edgeConnection[i][0]],
						cube[MarchingCubesCases.edgeConnection[i][1]]);

				edgeVertex[i].x = pos.x + (vertexOffset[MarchingCubesCases.edgeConnection[i][0]][0]
						+ offset * MarchingCubesCases.edgeDirection[i][0]);
				edgeVertex[i].y = pos.y + (vertexOffset[MarchingCubesCases.edgeConnection[i][0]][1]
						+ offset * MarchingCubesCases.edgeDirection[i][1]);
				edgeVertex[i].z = pos.z + (vertexOffset[MarchingCubesCases.edgeConnection[i][0]][2]
						+ offset * MarchingCubesCases.edgeDirection[i][2]);

			}
		}

		// Save the triangles that were found. There can be up to five per cube
		for (i = 0; i < 5; i++) {

			if (MarchingCubesCases.triangleConnectionTable[flagIndex][3 * i] < 0) {
				break;
			}

			idx = vertList.size();

			for (j = 0; j < 3; j++) {
				vert = MarchingCubesCases.triangleConnectionTable[flagIndex][3 * i + j];
				indexList.add(idx + MarchingCubesCases.windingOrder[j]);
				vertList.add(edgeVertex[vert]);
			}

		}
	}

	
	// GetOffset finds the approximate point of intersection of the surface
	// between two points with the values v1 and v2
	private static float GetOffset(float v1, float v2) {
		float delta = v2 - v1;
		return (delta == 0.0f) ? 0.5f : (target - v1) / delta;
	}
}

I can attach the look up tables if needed. The MeshData class is just a class to hold verts, indices, etc. The voxel data is generated using the generateVoxels method and it is for a size of 16. Finally the voxel material only maters if the material is air as then the voxel will need to be rendered. Any help would be amazing.

Thanks

Euan

Edited by thelordposeidon

Share this post


Link to post
Share on other sites
Advertisement
Posted (edited)

Your images are terrible quality, but it looks like you are not getting a manifold mesh out of your algorithm, so I expect you've got the cases wrong. Perhaps with larger, better lit images it would be clearer? While I'm not going to review your cases, I've recently posted a marching cubes tutorial, so you can look over my cases instead? I have unit tests for the case table, you could port that to see if your own table passes.

Otherwise, I'd start debugging your code. Marching Cubes is very easy to test a single cube in isolation, so I'd start with one you know to be wrong.

Edited by Boris The Brave
Extra text

Share this post


Link to post
Share on other sites

Thanks for the advice, I'll get some better quality images tomorrow for you, unfortunately I had to take them under some time pressure but tomorrow I shouldn't have that issue. I'll take a look at the tutorial and thanks for the unit tests, again I'll look at them tomorrow.

Share this post


Link to post
Share on other sites

Can you link to a pasteboard of the tables. I'm not sure why your marching cubes uses a windingOrder table (unless your culling direction is the wrong way)?

Share this post


Link to post
Share on other sites

Here's the pastebin : here, and the pictures will go up later. I added it because I was having some issues I think with direction culling and it seemed to help. This was awhile ago so I can't quite remember what I was doing.

Share this post


Link to post
Share on other sites
28 minutes ago, swiftcoder said:

Well, your tables look like standard marching cubes tables, so you can probably rule out issues there.

Yeah, I'm pretty sure it's me making a silly mistake or a mistake in logic

Share this post


Link to post
Share on other sites

So i took some more pictures and did some debugging. First and foremost here are some better pictures of the cube at the original size (16 x 16 x 16 in opengl world coords). I uploaded it to imgur here.

Next I tried some debuging. No cube shows when I have the grid size as 1 x 1 x 1. When it is 2 x 2 x 2 I get a small triangle (pic here) and finally when I do 4 x 4 x 4 I get this load of weirdness. Obviously my logic has gone wrong but honestly I have no idea where.

Any ideas would be amazing.

Share this post


Link to post
Share on other sites

Do you know of any off the top of your head that is similar enough that I can compare it easily?

Edit : So I found that good old scrawk's code is similar to mine (though in c# and using unity). So the plan is to try and use that as a debug tool as that is definitely confirmed working. See where the difference in logic and code is. If I find anything I'll post it here, if there's nothing feel free to offer suggestions on what's wrong in the code as I've probably not solved it.

Edited by thelordposeidon
uodate

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now


  • Advertisement