• Hey! Guest! The 36th GMC Jam will take place between February 27th, 12:00 UTC - March 2nd, 12:00 UTC. Why not join in! Click here to find out more!

3D 3D baby steps in GMS2

moogthedog

Member
I'm trying to start out with a spot of 3d, and I'm close... but it's defeating me at the last moment.

I've got a room set up with a camera layer and an instances layer. The camera layer is at the bottom of the heap, as I've read the camera object needs to be the furthest away.

In the room, I have six objects:
Camera layer: oCamera (?)
Instances: oPlayer (>), 3 oBlocks, and an oGlb (?) to hold any 'globals'
Grid's 32.

blockyroom.jpg

The player responds to keyboard commands (WASD to move, arrow keys to look, with up and down doing pitch), and that's working fine - there's no camera jiggery pokery in the player.

The block object has this in create:
Code:
height=32;

// define the vertex format - just position and colour for the moment
vertex_format_begin();
vertex_format_add_position_3d();
vertex_format_add_colour();
form=vertex_format_end();

// create a buffer
buf=vertex_create_buffer();


// add my primitives - just a standy-up triangle at the moment
vertex_begin(buf,form);
vertex_position_3d(buf,x,y-sprite_height,height);
vertex_colour(buf,c_white,1);
vertex_position_3d(buf,x,y-sprite_height,height);
vertex_colour(buf,c_red,1);
vertex_position_3d(buf,x,y,0);
vertex_colour(buf,c_blue,1);
vertex_end(buf);
which is aimed to create a single 3D triangle standing up in the Z direction, at the block's location.
This is in draw
Code:
vertex_submit(buf,pr_trianglelist,-1);

// also plot ourselves to the default camera (for the minimap)
draw_self();
which (I hope) submits the triangle to the default shader for rendering, as well as plotting the block to the default camera which is used to make a mini map (see below)

The oGlb object sets up the viewports in its create:
Code:
player=instance_nearest(0,0,oPlayer)
camera=instance_nearest(0,0,oCamera);

view_enabled=true;

///camera view
view_xport[0]=0;
view_yport[0]=0;
view_wport[0]=1024;
view_hport[0]=1024;
view_visible[0]=true;

///map view
view_xport[1]=0;
view_yport[1]=20;
view_wport[1]=100;
view_hport[1]=100;
view_visible[1]=true;
camera_set_view_pos(view_camera[1],0,0);
camera_set_view_size(view_camera[1],1024,1024);
Which sets up the view port for what's to be the roaming 3D camera, and a second standard camera for the mini-map.

The camera object has this for creation:
Code:
cam=camera_create();
camera_set_proj_mat(cam,matrix_build_projection_perspective(640,480,1,32000));
camera_set_view_mat(cam,matrix_build_lookat(0,0,0,1,0,0,0,0,1));

view_camera[0]=cam;
Where the camera is created and assigned to its viewport, and given a default set of matrices which will change as the player moves.
And then this in its draw event
Code:
x=oGlb.player.x;
y=oGlb.player.y;
var _cz=oGlb.player.z+oGlb.player.height;
direction=oGlb.player.direction;

var _tx=x+lengthdir_x(1,direction);
var _ty=y+lengthdir_y(1,direction);
var _tz=_cz+lengthdir_y(1,oGlb.player.pitch);

// version 1
camera_set_proj_mat(cam,matrix_build_projection_perspective_fov(90,1,1,32000));
// version 2
//camera_set_proj_mat(cam,matrix_build_projection_perspective(1024,1024,1,32000));

camera_set_view_mat(cam,matrix_build_lookat(x,y,_cz,_tx,_ty,_tz,0,0,1));
which forces the camera to track the player's position and 'head' (view direction).

Desired operation: Given the start positions, I'd expect the 3D camera to show me three triangles side by side, and I should be able to move around the world to look at them from different angles

In 'version 1' in the camera::draw, I get very close - the minimap is rendered in the sky, but is displayed sensibly - I think I know why that happens. As the player moves, the 'sky' tracks in and around the view correctly. If you pitch up, you can actually see the player's arrow following him around. Unfortunately the 'blocks' aren't rendered in the 3D realm at all - just as sprites in the sky. I've tried moving around to see if I've got the axes messed up, but they're just not there.

In 'version 2', I can see a single pure white triangle, but it stays solidly in the centre of the screen, changing shape slightly on player movement, and stretching oddly when the pitch changes. Changing the vertexes in block::create to change its width seems to have no effect, so I'm thinking I may not actually be looking at a block object at all.

Looking for any and all help, and please don't think anything's too obvious - I've spun this together from what I know of 2D cameras from my previous project and the tutorials, and the help. If it's easier, I can zip and upload the project to a server.
 

moogthedog

Member
I've just messed around with 'version 2' some more, and I can get a HUGELY distorted version of the minimap appearing in the area that the triangle was occupying before. Which was nice.

I tried adding a texture component to the block creation and draw code:

Code:
//block::create
height=32;

// define the vertex format - just position and colour for the moment
vertex_format_begin();
vertex_format_add_position_3d();
vertex_format_add_colour();
vertex_format_add_texcoord();
form=vertex_format_end();

// create a buffer
buf=vertex_create_buffer();


// add my primitives - just a standy-up triangle at the moment
vertex_begin(buf,form);
vertex_position_3d(buf,x,y-sprite_height,height);
vertex_colour(buf,c_white,1);
vertex_texcoord(buf,0,0)
vertex_position_3d(buf,x,y-sprite_height,height);
vertex_colour(buf,c_red,1);
vertex_texcoord(buf,1,0);
vertex_position_3d(buf,x,y,0);
vertex_colour(buf,c_blue,1);
vertex_texcoord(buf,1,1);
vertex_end(buf);
Code:
//block::draw
vertex_submit(buf,pr_trianglelist,sprite_get_texture(sprite_index,0));

// also plot ourselves to the default camera (for the minimap)
draw_self();
but no change :(
 

moogthedog

Member
OK - so I found this guide, which I've retro-ed into my project and got it working. I think I was both missing the gpu_* commands at the start, and also messing up the positioning of my sprites in the world space.

Now I've got another peculiarity:

The texture is being applied in block::draw, and *outght* to be a single sprite texture:
Code:
vertex_submit(buf,pr_trianglelist,sprite_get_texture(sprCirc,0));
but instead the texture actually displayed is a blob of all three sprites in my project:

image1.png

even though the UVs for the texture only go from 0 to 1:

Code:
// block::create excerpt

// add my primitives - just a standy-up triangle at the moment
vertex_begin(buf,form);

//T1
vertex_position_3d(buf,x-height,y-height,-height+oGlb.heightOffset);
vertex_colour(buf,c_white,1);
vertex_texcoord(buf,0,0)
vertex_position_3d(buf,x+height,y-height,0+oGlb.heightOffset);
vertex_colour(buf,c_red,1);
vertex_texcoord(buf,1,0);
vertex_position_3d(buf,x-height,y+height,0+oGlb.heightOffset);
vertex_colour(buf,c_blue,1);
vertex_texcoord(buf,0,1);

//T2

vertex_position_3d(buf,x-height,y+height,0+oGlb.heightOffset);
vertex_colour(buf,c_blue,1);
vertex_texcoord(buf,0,1);

vertex_position_3d(buf,x+height,y-height,0+oGlb.heightOffset);
vertex_colour(buf,c_red,1);
vertex_texcoord(buf,1,0);

vertex_position_3d(buf,x+height,y+height,height+oGlb.heightOffset);
vertex_colour(buf,c_red,1);
vertex_texcoord(buf,1,1);

vertex_end(buf);
If I change the 'sprCirc' to something else, the image remains the same. Changing the 1s to 0.5s in the texcoord elements just plots the block sprite (again, no matter what sprite is actually chosen in vertex_submit). This means I'm getting the UVs right, but the texture being passed to the graphics pipeline is wrong...

Additionally, if I look at the scene so the primitives are rendered in order, back to front, (as in the image above) all is fine:

but if i move the camera so the ordering goes front-to-back, the alpha-0 parts of the textures get messed up...

image2.png

This is a question of the ordering of the vertex_submit calls, as if I swap the sprites around in the room so they're rendered top-bottom-middle (by id order, as shown in the second line of text) I end up with some very odd effects...

image3.png
('front' texture is obscuring the middle one, but middle doesn't obscure the back)

image4.png
(the same, but if you look at the minimap, we're looking from the other end now)

It seems that the alpha-0 parts of the textures are actually getting rendered as background.

Any thoughts greatly appreciated.
 
Top