Jump to content


Photo

Precise 3D Collisions Dll (P3DC.dll) V6.1


  • Please log in to reply
375 replies to this topic

#1 brett14

brett14

    GMC Member

  • GMC Member
  • 1150 posts
  • Version:GM8

Posted 05 October 2009 - 12:09 AM

Posted Image
Now supports GM8.1!

Examples for V6.1 are in GM8.0 format, so GM7 users have to convert it using LGM or use V5.02.

Download V6.1 (zip) - Comes with source [Newest Version]
*Older Versions*
Download V6.00 (.zip), Download V6.00 (.7z), Download V5.02 (.zip), Download V5.01 (.zip), Download V5.00 (.zip), Download V4.00 (.zip)

**V6.1 changes one line of code, that fixes a crash that some people were randomly encountering sometimes. It still uses all V6.00's scripts.

Features:
-Accurate collision between 2 models
-Raycasting
-Load external models (.d3d models -> GM's format)
-Create the model in game
-Optimize you're meshes (mainly the level) to increase frame rates.
-Find a triangles normals, and vertex coordinates
-Rotations
-More


CREDIT
Brett Binnersley (Brett14): Made P3DC
Samuel Hanson (Hanson): Made ModModCollisions, P3DC is based on it.
Snake_PL: P3DC V5.02 makes use of GMAPI. V6.00 is GMAPI free.
Thomas Moller: 3D Collision code, some of it is used by P3DC
Chessmasterriley: For making the logo.

Problems Loading Your Model?
Trouble getting models to load? Follow These Instructions
If the above does not work, there may be an error in the source code. P3DC is open source, feel free to fix it.


Please leave feedback, report bugs, and request features you'd like to see.
~~Brett14;

PS: Check out my newest project: GameDev Studio

Edited by brett14, 16 March 2012 - 07:43 PM.

  • 5

#2 frankpiet

frankpiet

    ^destroyed evil chicken^

  • New Member
  • 760 posts

Posted 05 October 2009 - 01:46 AM

Good job!
construction:
good, as proven campared to modmod
possibly make it an extension, with a help file. just for convenience -_-

presentation:
great, indented code. enough comments to understand it, some more wouldnt hurt.
maybe make the beginner game 3rd person, with the ability to change player models, to demonstrate its full capabilities

extra features?
maybe a feature that returns a vector representing a polygons upside?

anyway 9.5/10
  • 0

#3 brett14

brett14

    GMC Member

  • GMC Member
  • 1150 posts
  • Version:GM8

Posted 05 October 2009 - 04:29 AM

Thanks Frank;

I don't plan to make a help file, Although I may add a few more comments. I might add a 3rd person option, but that doesn't really show much more of the dll. That would show what gm's D3D can do. I might add a few models flying into each other or something though.
  • 0

#4 hanson

hanson

    GMC Member

  • GMC Member
  • 444 posts
  • Version:GM8

Posted 06 October 2009 - 01:07 PM

Looks nice! I'll be trying this out as soon as I find where I hid my gm7 reg info. Thanks for sharing your modifications!
  • 0

#5 WadeMcGillis

WadeMcGillis

    wademcgillis.com

  • GMC Member
  • 971 posts

Posted 06 October 2009 - 02:25 PM

In the expert example, it says that modmod was made by hobbel...
  • 0

#6 hanson

hanson

    GMC Member

  • GMC Member
  • 444 posts
  • Version:GM8

Posted 06 October 2009 - 02:34 PM

And in the op :rolleyes: This is incorrect though. I'm sure it was just a copy-paste-forget.to.edit scenario and will be fixed soon now that it was brought up.
  • 0

#7 brett14

brett14

    GMC Member

  • GMC Member
  • 1150 posts
  • Version:GM8

Posted 07 October 2009 - 12:52 AM

Sorry! It was made my hanson, not hobbel... I confused the names of you two. I'll fix it in the next update. I'll also update the first post (to ensure people know). It was a copy-paste error, It will be fixed.

Once again sorry
~~Brett14;

[EDIT]
Btw: This message is directed towards you Frankpiet, you wanted me to make a game? Good news, I'm making one; this is why this was developed. I needed fast collisions-so I made this. It is a 3D Multiplayer game (the expert example is actaully a level from it without the models and the textures)
[/EDIT]

Edited by brett14, 07 October 2009 - 01:25 AM.

  • 0

#8 Jepie0

Jepie0

    GMC Member

  • GMC Member
  • 213 posts

Posted 07 October 2009 - 01:50 AM

Thankyou Brett14 for continuing hanson's collision dll. I had previously tried hansons version and while it was impressive in concept i found it hard to implement and it tended to by rather unstable at times. Whereas your version is much more simple to implement and use. I am currently using the dll for instant terrain collisions, on a 64x64 terrain consisting of 8192 polys im getting 120fps which is awesome. My previous attempts at doing instant terrain collisions with just pure gml slowed the game down to 4-5fps. So overall congratulations on creating a dll that should become an essential element of any 3d game made with gamemaker.

Wish list:
Possibility of ray casting returning a normal.
(Parent / Child hierarchy), being able to group models in the dll.
So for instance being able to say add 10 boxes to a collision group and then instead of going threw all the objects/models comparing in gm this would be done on the dll side.
The dll then could return a specific id relating to one of the 10 box instances in that group. This would be usefull for knowing which box was hit so u could then change it to a broken box.
Material properties either per face or as above for individual models within a group. Simply being able to set a face or model with a material property of (0-255) would allow for knowing which particle effect to create for a raycast collision.
Rotation of support.
Being able to tell the dll to load a external model (.mod, .obj etc) and use it for collisions.
This would be alot faster than gamemaker having to load a model then break it down and pass on each poly to the dll.
Xygthop3 adapted a script for use with hansons dll to load a .obj into gamemaker that generated a .mod file and collision for the dlll.

The (Parent / Child hierarchy) and material ideas could be done in gamemaker but that would require all model and ray cast comparisons to be done in gamemaker. If i had 10 boxes with different material properties i would have to repeat a raycast 10 times and then via a custom script return the closest box. I think this would be better done inside the dll to further expand the Possibilitys of 3d gamemaker.

Cheers Brett14 keep up the good work, Jepie0
  • 0

#9 brett14

brett14

    GMC Member

  • GMC Member
  • 1150 posts
  • Version:GM8

Posted 07 October 2009 - 02:03 AM

Whereas your version is much more simple to implement and use

should become an essential element of any 3d game made with gamemaker.

Thank you.

(Parent / Child hierarchy)

This is a very good idea, however I have not gotten a clue how this would work. If I follow you'd like it so that say we have 3 objects, you can add them all to the dll and it will calculate them for you. So for example we add 3 box objects to the dll, and whenever they move the dll will detect this and update their collision, and when they collid it will auto detect what to do with them. If you have an idea of how to do this please tell me (or send me a link). Please note, I'm not an expert c++ user (However I am an expert gm user). This is only my 2nd time ever using c++... my first was a helloworld program then I didn't come back until this-because I needed fast collisions for a game and modmod was too slow (the reason for that was rotations, that's why they have been ripped out). The only reason it was possible for me to make this is that gml and c++ are very similar.

Being able to tell the dll to load a external model

Currently, At the moment this is my top priority. The first thing I'm trying to do is get models to load in Gamemaker via gml. Once I get this done I'll attempt to convert it over to the dll, to load them through that. I'll have to look at a tutorial or something first though to see how to manage strings and files in c++. Currently you can only load models through your own code/loading type.

[EDIT]
Do you know where a documentated version of the gm model format is? That'd help me make loading models alot easier. Thanks
[/EDIT]
~~Brett14;


[EDIT2]
The next version will contain a "split" model example. This is done purely on the gamemaker side, and can boost speeds massivly. This is done by splitting the collision model into an [X,Y] array of models, then you see which model to collision check against through some simple math. This can reduce the number of polygons becing checked from like 2000 to 10-100. In the experts example I've already done this and I can do 400 raycasts @ 900 fps (capped by gpu, not cpu), whereas without this I'm getting 150-300~
[/EDIT2]

Edited by brett14, 07 October 2009 - 02:12 AM.

  • 0

#10 Jepie0

Jepie0

    GMC Member

  • GMC Member
  • 213 posts

Posted 07 October 2009 - 02:33 AM

What i meant by the (Parent / Child hierarchy) system was being able to add models to the dll but the added models would be assigned a individual id and be assosicated with a group. So when u do a ray cast collision check instead of checking one model id u would be checking a group and all of its models under that group. An easy why to explain it would be via how i imagine the gml would look.

// create event
box_collision_group = p3dc_create_group(); // generates a collision id group

box_col_0 = p3dc_create_group_child(box_collision_group); // dll returns a new id within group
p3dc_add_external_model(box_col_0,"box_metal.obj"); // tells dll to externally load a model and associate it with the child

box_col_1 = p3dc_create_group_child(box_collision_group); // dll returns a new id within group
p3dc_add_external_model(box_col_1,"box_wood.obj"); // tells dll to externally load a model and associate it with the child

box_col_2 = p3dc_create_group_child(box_collision_group); // dll returns a new id within group
p3dc_add_external_model(box_col_2,"box_rock.obj"); // tells dll to externally load a model and associate it with the child

p3dc_group_end(); // ends the group

// draw event when checking for collision
col_dis = p3dc_group_distance_ray_still(box_collision_group,cam_x,cam_y,cam_z,vx,vy,vz); // would check all instances in the group and return the shortest distance
col_id = p3dc_group_id_ray_still(box_collision_group); // returns the last ray collisions found id instead of having to redo a ray cast
col_material = p3dc_group_material_ray_still(box_collision_group); // returns the last ray collisions found material instead of having to redo a ray cast
nx = p3dc_group_normal_ray_still_nx(box_collision_group); // returns the last ray collisions found normal instead of having to redo a ray cast
ny = p3dc_group_normal_ray_still_ny(box_collision_group); // returns the last ray collisions found normal instead of having to redo a ray cast
nz = p3dc_group_normal_ray_still_nz(box_collision_group); // returns the last ray collisions found normal instead of having to redo a ray cast

I'll have alook for the gm model format thing and pm u if i find anything.

Cheers, Jepie0

Edited by Jepie0, 07 October 2009 - 02:37 AM.

  • 0

#11 brett14

brett14

    GMC Member

  • GMC Member
  • 1150 posts
  • Version:GM8

Posted 07 October 2009 - 02:46 AM

I'm starting to understand what your asking *I think*. What you want is to create a model group, and when you add a block to the collision group it will be given a unique ID (say the objects id in gm for example). Then when you colid with that group, return the ID of the hit block instead of just 1(true) for a collision or 0(false) for no collision?

Edited by brett14, 07 October 2009 - 02:47 AM.

  • 0

#12 Jepie0

Jepie0

    GMC Member

  • GMC Member
  • 213 posts

Posted 07 October 2009 - 02:50 AM

Yeah thats pretty much it each model under a group would have a unique id and that would be returned. That would open the door for some awesome 3d games currently all the dll can do is just return a distance that then can be used to find a x,y,z position collision.

Example pic of what im working on using your dll to get instant terrain collisions.
Posted Image

Cheers, Jepie0
  • 0

#13 brett14

brett14

    GMC Member

  • GMC Member
  • 1150 posts
  • Version:GM8

Posted 07 October 2009 - 02:56 AM

Yeah thats pretty much it each model under a group would have a unique id and that would be returned. That would open the door for some awesome 3d games currently all the dll can do is just return a distance that then can be used to find a x,y,z position collision.

This can already be done quite fast through gml, however I'll add it to the dll to make it simpler to use (and possible a little faster). I think you'd already know how it would be done (same way as modmod does it, you can look at his example) but I'll try to get this in asap. My priority at the moment goes to loading the collision model though. Then I'll try to add this.


---------------BELOW TO SEE HOW TO SHOOT MULTIPLE OBJECTS, AND SEE WHICH IS CLOSEST---------------
[EDIT]
This is the code I'm using to see if I shot a person, and if I did which one I shoot. (Always is the closest, or the level, or nothing)
dis=p3dc_ray_still(levelcolid,x,y,z,vx,vy,vz);//shoot to see how far it is to the level, Returns 0 if shot into space
hit=noone;//Currently we have shot nobody


with(objh_dummy){
var d;
d=p3dc_ray(global.player_collision,x,y,z-5,other.x,other.y,other.z,other.vx,other.vy,other.
vz);//check to see if there was a collision with this player in the given direction
	if(d<other.dis){//if there was AND it is less than the distance to the level
	other.dis=d;//The distance is now to this player (he's the closest)
	other.hit=id;//We set hit to this objects id, becuase we hit it.
	}
}

if dis==0 exit;//Nothing was hit, he shot into space

//If we didn't hit anybody
if(hit==noone){
//EFFECT
exit;//exit
}
with(hit){
//What to do with the hit object
}
[/EDIT]

Edited by brett14, 07 October 2009 - 03:13 AM.

  • 0

#14 Jepie0

Jepie0

    GMC Member

  • GMC Member
  • 213 posts

Posted 07 October 2009 - 03:23 AM

Thanks for the code brett14, im already well aware of how todo the child/parent and material idea in gml i just think the less work gm has todo the better. I just wanted to avoid having todo a giant with loop to compare the returned dll values. Will u be adding normal support in the next release? code wise it should be fairly easy to implement even in c++.

gml normal code
nx = (yy2-yy1)*(zz3-zz1) - (yy3-yy1)*(zz2-zz1);
		ny = (zz2-zz1)*(xx3-xx1) - (zz3-zz1)*(xx2-xx1);
		nz = (xx2-xx1)*(yy3-yy1) - (xx3-xx1)*(yy2-yy1);
		m = sqrt(nx*nx + ny*ny + nz*nz);
		nx /= m;
		ny /= m;
		nz /= m;

Cheers, Jepie0
  • 0

#15 brett14

brett14

    GMC Member

  • GMC Member
  • 1150 posts
  • Version:GM8

Posted 07 October 2009 - 03:33 AM

Thanks for the code brett14, im already well aware of how todo the child/parent and material idea in gml i just think the less work gm has todo the better. I just wanted to avoid having todo a giant with loop to compare the returned dll values. Will u be adding normal support in the next release? code wise it should be fairly easy to implement even in c++.

gml normal code

nx = (yy2-yy1)*(zz3-zz1) - (yy3-yy1)*(zz2-zz1);
		ny = (zz2-zz1)*(xx3-xx1) - (zz3-zz1)*(xx2-xx1);
		nz = (xx2-xx1)*(yy3-yy1) - (xx3-xx1)*(yy2-yy1);
		m = sqrt(nx*nx + ny*ny + nz*nz);
		nx /= m;
		ny /= m;
		nz /= m;

Cheers, Jepie0

I agree that less gm=better, normal code probably won't be in the next release.

-----------EDIT-----------


[EDIT]
Okay Jepie, or anybody else that is interested. I'm just starting to plan how I'd add what you want to the dll. So far I have this idea. However there are a few "problems" with it.


Step #1: (Load/Create the models - Same as it is now)
model=p3dc_model_load("playermodel.d3d");//Load the model, working on

Step #2: Create a group
playergroup=p3dc_group_create();

Step #3: Add the models to the group (that were created in step one)
p3dc_group_add(model1,x,y,z,ID NUMBER);
p3dc_group_add(model2,x,y,z,ID NUMBER);
p3dc_group_add(model3,x,y,z,ID NUMBER);
p3dc_group_add(model3,x,y,z,ID NUMBER);//this one was needed twice

Step #4: Close/Finish making the group (the same model will be allowed in multiple groups with DIFFERENT ID's in each one (or the same)) 0 will be reserved for no collision
p3dc_group_finish();

Step #5: Do a collision check (or ray cast) on the group and return the ID of the hit object defined in step 4. If it returns 0, nothing was hit. If it returns anything else that was the object that was hit.
hit=p3dc_group_check(group ID,Checking Args);//Group ID is returned by step 2


This is basically the layout I have for it right now. However, I have a few problems (for you to answer). How do you want to "update" the group because a player in it moved? Or would you like groups to be collections of non-moving objects with ids? How would you like to see this work?

[/EDIT]

~~Brett14;

Edited by brett14, 07 October 2009 - 04:03 AM.

  • 0

#16 Jepie0

Jepie0

    GMC Member

  • GMC Member
  • 213 posts

Posted 07 October 2009 - 04:15 AM

Its looking good thats basically the concept i was going for. As for the updating i guess a script would need to be called in the step event of the moving object to update its x,y,z position to the dll. If a object does not update its x,y,z it would just be treated as a static object in the dll. Will there be seperate ray casting scripts to return distance and id?

In the below code will the ID NUMBER have to be manually pre-defiend or is that where the playergroup id goes? because p3dc_group_add should probably return a unique id so it can be passed onto a object for future use.

p3dc_group_add(model1,x,y,z,ID NUMBER);
p3dc_group_add(model2,x,y,z,ID NUMBER);
p3dc_group_add(model3,x,y,z,ID NUMBER);
p3dc_group_add(model3,x,y,z,ID NUMBER);//this one was needed twice

Thanks, Jepie0

Edited by Jepie0, 07 October 2009 - 04:17 AM.

  • 0

#17 brett14

brett14

    GMC Member

  • GMC Member
  • 1150 posts
  • Version:GM8

Posted 07 October 2009 - 04:31 AM

There will be two different sets of id's.

Groups Ids and the model id's inside of the groups

for example

-group1, Id 1
---model1, Id 1
---model2, Id 2
---model3, Id 3
-group2, Id 2
---model 1, Id 1
---model 1, Id 2
---model 2, Id 3
---model 2, Id 4

So every group has it's own id returned by p3dc_group_create() and in every group you would place models. To answer your question for short, you will be able to add more than 1 group. If your just checking two models, then we would continue like normal. (Unless raycasting, then we'd check them both)

Will there be seperate ray casting scripts to return distance and id?

What I'm thinking right now is call the raycast script, which will return the id of the hit object, and it will store the distance in a variable. Then you'll call
p3dc_get_dis();
right after that, and it'll return the stored varaible for the distance of the last raycast.



However, updating the positions every step brings in another problem. It would be much slower to call the dll in every object every step than one gml loop to do the shooting collisions. How should we get around this? I'm thinking making the groups, but only use them for things like the level. Using it every step in 10 players would be slow.

Edited by brett14, 07 October 2009 - 04:37 AM.

  • 0

#18 Jepie0

Jepie0

    GMC Member

  • GMC Member
  • 213 posts

Posted 07 October 2009 - 04:51 AM

Only the moving objects would need there x,y,z positions to be updated. As for possible alternatives i came up with 2 ideas.

The first idea would be to not only do collisions in the dll but also basic movement physics, so the dll would move the objects around with xspeed, yspeed, zspeed and friction then there would be no need for constant updating. But the simulation would have to be identical in both gamemaker and the dll which would be hard.

Idea 2 would be just before doing a ray cast group check running a script that via a with loop updates the groups x,y,z position. The problem here is that if there is a large amount of objects in the group it could lead to a big loop.

Im not sure there is a way around not updating moving objects fairly constantly. But having seperate scripts for defining static and moving models would be good. The level and basic objects grouped in it will more than likely all be static only players and npcs etc would need to have there positions passed onto the dll.

Thanks, Jepie0
  • 1

#19 brett14

brett14

    GMC Member

  • GMC Member
  • 1150 posts
  • Version:GM8

Posted 07 October 2009 - 05:05 AM

Number one would just lead to unneeded complication (and It'd be slower)

Think about number two.

Do a gml loop to update the objects and then call the c++ code to check
-or-
we can run a gml loop and check at the same time.

So I'll add groups, they will be able to move, but it'll be faster to do a GM loop. If they are static, use your own loop because it'll be faster than doing a loop to update the objects and then calling a function to check, however the option to update the groups is there. How's that sound?

Edited by brett14, 07 October 2009 - 05:07 AM.

  • 0

#20 Jepie0

Jepie0

    GMC Member

  • GMC Member
  • 213 posts

Posted 07 October 2009 - 05:15 AM

Yep sounds good i was only throwing some ideas around. Leave the position updating to the user to decide when to update individual model positions.

Cheers, jepie0
  • 0




1 user(s) are reading this topic

1 members, 0 guests, 0 anonymous users