Hi !
Featured games (90)
games approved by the League of Dukes
Games in Showcase (710)
Games in Android Showcase (212)
games submitted by our members
Games in WIP (784)
games currently in development
News: Read the Java Gaming Resources, or peek at the official Java tutorials
    Home     Help   Search   Login   Register   
Pages: [1]
  ignore  |  Print  
  [Manipulating Pure Java2D into 3D (Software)]  (Read 3946 times)
0 Members and 1 Guest are viewing this topic.
Offline GabrielBailey74
« Posted 2013-01-25 21:24:59 »

Hey JGO, before I start this post I'd like to say that this post and the snippets are open to criticism Cheesy.

I'm not too sure if many people are familiar with this, so I figured I'd post it here. Smiley

The effects this code will produce vary, so I will post the screenshots at the end of this post.

Knowledge of copy & paste.
Basic Window setup.
Canvas / JPanel setup.
Basic game loop setup for updating and rendering.

Assuming that you've:
A: Created a Window (JFrame), and added a Canvas (Or JPanel) to it.
B: Implemented a basic game loop that covers updating and repainting the drawing area.
Lets continue. Cheesy

Somewhere in your application you'll need to declare these variables:
(They will be needed to create a Array[] of pixels and render them)
private static final int ALPHA = 0xFF000000; // Same as: -16777216
private Graphics graphics;
private int pixels[];
private Image img;
private MemoryImageSource mis;
private int width, height;

In your application you'll need to initialize the variables above like so:
(Preferably in the constructor)
width = getSize().width; // Obtain your Windows width.
height = getSize().height; // Obtain your Windows height.
pixels = new int[width * height];
for (int i = 0; i < width * height; i++) {
   pixels[i] = ALPHA + (int) (Math.random() * 256 * 256 * 256); // Initialize the pixels so they're visible.
mis = new MemoryImageSource(width, height, pixels, 0, width);
img = createImage(mis); // Create the Image via your Window.
graphics = getGraphics(); // Obtain the Graphics via your Window.

Now that we've initialized all of our variables, you're free to start your game loop and add the following to your render method to draw the pixels:
graphics.drawImage(img, 0, 0, null);

If you were to run the above it should produce the following:
(If you want the pixels to constantly change, just add the pixel initialization code before your draw the Image and call: mis.newPixels())

If you want to compare your setup with how it should be, see the completed class here:

Now we get to the fun part Cheesy transforming 2D pixels into what seems to be 3D.

Above the call to 'mis.newPixels()' and 'graphics.drawImage()' add the following, we'll perform the transformation to 3D:
(Coincidentally we'll also be implementing variables to control the left/right rotation and position of the '3D Camera' Cheesy)
               /* Begin the transformation to 3D */
               double ceilingPosition = 8.0;
               double floorPosition = 8.0;
               double cameraYPosition = 1.0;
               double up = 1.0;
               double rotation = 0.0;
               double cosine = Math.cos(rotation);
               double sine = Math.sin(rotation);
               double forward = 0.0;
               double right = 0.0;
               int ceil = 0;
               for (int y = 0; y < height; y++) {
                  if (y < 0 || y >= height) continue;
                  double ceiling = (y + -height / 2.0) / height;
                  double z = (floorPosition + cameraYPosition + up) / ceiling;
                  if (ceiling < 0) {
                     z = (ceilingPosition - cameraYPosition - up) / -ceiling;
                     ceil = 1;
                  for (int x = 0; x < width; x++) {
                     if (x < 0 || x >= width) continue;
                     double depth = (x - width / 2.0) / height;
                     depth *= z;
                     double xx = depth * cosine + z * sine;
                     double yy = z * cosine - depth * sine;
                     int xPix = (int) ((xx + right) * 4);
                     int yPix = (int) ((yy + forward) * 4);
                     /* Apply the transformation to the pixels */
                     pixels[x + y * width] = ALPHA +  ((xPix & 15) * 16) | ((yPix & 15) * 16) << 8;

If everything was done correctly you should see the following:
(Looks like 3D Space hmm?)

Result before applying depth transformation:

Various results from manipulating pixels:
(Rotation is active in some screenshots, thus the angle looks different)

If you'd like to compare your end result with the complete class see here:

There is more than one way to do this, in this example I chose to use the MemoryImageSource over BufferedImage. (Reason why alpha is not just 0xff)
It is possible to create simple 3D objects and render them. (Walls, boxes etc, basic geometry)
In the example, Thread.sleep is not implemented, just realized that.
It is possible to apply textures, created this as an example:

Well, thanks for reading guys.
This post should be enough to get someone started on manipulating 2D into 3D.
Looking forward to some feedback, have a nice day.

Offline Ultroman

JGO Knight

Medals: 25
Projects: 1

Snappin' at snizzes since '83

« Reply #1 - Posted 2013-01-26 06:19:25 » mind is blown. I'd love to see that in realtime

- Jonas
Offline Alan_W

JGO Knight

Medals: 8
Projects: 3

Java tames rock!

« Reply #2 - Posted 2013-01-26 08:34:13 »

This technique works fine in realtime for games written as 600x400 applets.  The basic renderer runs Ok for 800x600, but performance gets a bit iffy on slower machines, once you add extra graphics for moveable objects and game AI etc.  I've used variations on this in Java4k over many years, including my entry for this year (Die Z).  The trick is to come up with an algorithm that minimises overdraw.

Time flies like a bird. Fruit flies like a banana.
Games published by our own members! Check 'em out!
Legends of Yore - The Casual Retro Roguelike
Offline Ultroman

JGO Knight

Medals: 25
Projects: 1

Snappin' at snizzes since '83

« Reply #3 - Posted 2013-01-26 09:36:01 »

Oh, and can I see a screenie of that last one before the 3D is applied? I think it'll give me a better understanding of what's going on.

- Jonas
Offline GabrielBailey74
« Reply #4 - Posted 2013-01-27 02:00:23 »

Oh, and can I see a screenie of that last one before the 3D is applied? I think it'll give me a better understanding of what's going on.

You're talking about the very last screenshot where textures are being applied?

If so here's textured (Non 3D):

And here's non-textured (Non 3D).

Minor Y axis offset due to deactivated 3D physics.
Ceiling rendering is disabled (Non textured / Visible).
Textures can range from 8x8 to 32x32 (Grid)

Offline GabrielBailey74
« Reply #5 - Posted 2013-01-27 02:08:32 »

Trying to make the top fold in >.<
So the box has a top Cheesy

Offline Ultroman

JGO Knight

Medals: 25
Projects: 1

Snappin' at snizzes since '83

« Reply #6 - Posted 2013-01-27 02:19:57 » do you know to put the smiley-face texture weirdly offset like that to make it work? I sort of see how the mask-thingie will "stretch" the texture onto the "floor" / the lower half of the screen. But I'm still struggling to see how a 2D scene suddenly gets a third dimension, so that you can walk around on the ground. But I guess that's what your project here is all about.

EDIT: Just looked at the code again. You're just faking the third dimension with the floor and ceiling. I think I get it.

- Jonas
Offline GabrielBailey74
« Reply #7 - Posted 2013-01-29 21:31:55 »

I ported this to LWJGL overnight Cheesy wasn't as much fun though :s

Yeah, for the most part that's what's going on here, infinite floor and ceiling plus movement / 3D rotation.

If you just block out the space between them like so:
(With different textures applied to the ceiling/floor so we can tell the difference between them)

You get the feeling of walking around in a 3D scene.

Pages: [1]
  ignore  |  Print  
You cannot reply to this message, because it is very, very old.

numerical (74 views)
2017-02-21 07:32:16

numerical (75 views)
2017-02-21 07:31:46

theagentd (179 views)
2017-02-18 13:42:33

theagentd (182 views)
2017-02-18 13:35:16

h.pernpeintner (1345 views)
2017-01-24 22:39:11

h.pernpeintner (1333 views)
2017-01-24 22:38:32

Galdo (1894 views)
2017-01-12 13:44:09

Archive (1983 views)
2017-01-02 05:31:41

0AndrewShepherd0 (2519 views)
2016-12-16 03:58:39

0AndrewShepherd0 (2310 views)
2016-12-15 21:50:57
List of Learning Resources
by elect
2016-09-09 09:47:55

List of Learning Resources
by elect
2016-09-08 09:47:20

List of Learning Resources
by elect
2016-09-08 09:46:51

List of Learning Resources
by elect
2016-09-08 09:46:27

List of Learning Resources
by elect
2016-09-08 09:45:41

List of Learning Resources
by elect
2016-09-08 08:39:20

List of Learning Resources
by elect
2016-09-08 08:38:19

Rendering resources
by Roquen
2016-08-08 05:55:21 is not responsible for the content posted by its members, including references to external websites, and other references that may or may not have a relation with our primarily gaming and game production oriented community. inquiries and complaints can be sent via email to the info‑account of the company managing the website of java‑
Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines | Managed by Enhanced Four Valid XHTML 1.0! Valid CSS!