Ambiera Forum

Discussions, Help and Support.

Ambiera Forum > CopperCube > Programming and Scripting
ccbDoesLineCollideWithBoundingBoxOfSceneNode()

csp-games
Guest
Quote
2022-02-14 13:04:21

This is a very useful function that can be used right away to trigger the death of an NPC that was shot, but I am not sure whether I get this right:

When the NPC is hidden by eg. a Tree, is it still returning true (when used with camera and NPC positions). Or is it returning true only when colliding with the unculled backfaces of the tree. I tested it and it was kind of inconsistent. I guess the obstruction feature in this respect cannot be defined per node?


just_in_case
Moderator
Quote
2022-02-15 04:23:15

It will always return true if the line's endpoint is the position of the same object with whom you are checking the collision.

for example if you are checking collision for an NPC but also using the line going from camera to NPC, then it will always return "true", you either need to draw line to the "tree" instead of NPC, and check the collision with the bounding box of NPC, now it will return true only if your NPC is in front of the tree, that is in between the camera and the tree, otherwise it will return false if the NPC is behind the tree or somewhere else.

hope whatever I said above makes sense.

you can use
ccbGetCollisionPointOfWorldWithLine(startX, startY, startZ, endX, endY, endZ)
to check the actual collision point of the line, regardless of the object.

So you can use this command to draw a line from your camera to your NPC and if there is any obstruction in between then it will return the Point of obstruction if you know the width of your NPC or you can create a radius around your NPC, and check if the collision point is inside that radius then, the line is colliding with your enemy but if the collision point is outside the radius then it is not colliding with your enemy.

hope the above statement makes sense too. As far as I know, this is how it works, but too many collision checks might affect the performance.


csp-games
Guest
Quote
2022-02-15 12:22:26

Thank you very much just_in_case.
I guess there is even a simpler solution, and that is by using Nikos example that checks a line between camera and this:

var endPoint3d = ccbGet3DPosFrom2DPos(mouseX, mouseY);

It works for shooting the NPC, but, and that's my next problem, I have made a cube that I then try to position at this end point, by setting its position attribute. (I can use this 3d vector right away, right? Tho I tried both, one endPoint3D, or endPoint3d.X,endPoint3d.Y..., neither was working), but despite the cube being displaced from its initial location to somewhere, it does not appear where I'd expect it.

Any Idea what's wrong?


csp-games
Guest
Quote
2022-02-15 17:17:12

Ok, the fog is clearing up, I am beginning to understand.

The 2D to 3D function always returns a projected location at the max camera range (far plane), so if I'd look up 90 degrees, it'd be 0,2000,0.

The other function I've just tested, the problem is now; it ignores alpha-masked textures and seemingly also animated meshes.

Yeah, that would have been too easy, wouldn't it ^^


csp-games
Guest
Quote
2022-02-15 19:40:45

Ok, now I understand it depends on whether the geometry in between has collision on.

So I guess I will just parent the NPC to an invisible cube that has collision on. I was about to do that anyway. For the trees too, I will position cubes around the stem for collision. The only problem now is, I thought I'll get away with only a few cubes around the trees that are nearby the player, but what if an NPC hides behind a distant tree? I can't possibly have boxes around every tree - I had by accident collision on for the trees, and the slowdown way too much - even with only 4 Triangles per tree.

BTW speaking of trees, I did a little makeover, the trees have now more contrast within, using lit renders, and despite the shadows are relatively random, it looks better IMHO.
But I still use brightness variation, otherwise it's just too boring.

🔎︎



just_in_case
Moderator
Quote
2022-02-15 20:34:25

Awesome, glad that you finally understood how to use the the command, to get rid of usage of cubes for the trees, you can try, converting the trees into static animated meshes, then you can create collision for them in the animation editor. If you have seen the trees of inbuilt terrain of CC, they also uses the same techniques, though am not sure if it will work with the collision check command or not as there will be no collision for the nide actually.

By the way if your trees are static meshes then you don't need to have boxes for the collision, they all will already have collision, just make sure the collision attribute property of the model is checked.

But I highly recommend using "static animated model" as you will never want to have collision for the the leaves, which is in real simple quads/ traingles.

However as I mentioned in my previous comment, collision checking is a heavy task in CC and can affect the performance drastically, so use it carefully.
That is the reason why I proposed you to check the collision point of the world, wo that it will handle one command, which is drawing line from camera to NPC, and if the collision point is out for radius defined by you, the radius will be used to meausre the size of NPC usually width, wo basically you will be creating a virtual elipsoid around the NPC and if the line returns a point outside the radius then you can conclude that the NPC is behind something but if the collision point is inside the radius then, you can conclude that there is nothing in front of the NPC that is NPC is not hiding behind anything.

As this method includes only 1 collision check command, without any for loop or anything , this will not affect the performance that much.

But before going with this method or something else try giving the animated static mesh a shot.
If that works for you. But again if you are going to check collison with all the trees, it might affect the performance.

Hope this will not affect your game that much.


csp-games
Guest
Quote
2022-02-16 00:49:52

just_in_case, thank you very much. I guess I missed to explain the current situation clearly and in short terms.

-I cannot use collision directly, as the trees are doublesided, alpha-masked meshes with huge areas being transparent. They are extremly sticky when you walk into it, very useless for collision.

-The trees are one single mesh of 1200 trees, i can't handle them individually. If these were 1200 tree nodes, the framerate would be below 1 fps. This is really the lesson I've learned. Having many clones in WebGL: very slow. Having a few mega-meshes (all grass, all trees, all reef, the terrain) renders decently with the power of the GPU. So I will not give that up. "The static animated model" requires the trees to be individual nodes, so. that won't solve it.

-The Line Collision with World thing works well with meshes, when they have collision turned on, like walls and such so no problem there. The problem is more like I can't have collision boxes around trees in the distance, only to allow an NPC to take cover behind a tree.

I could however place a few collision boxes around all trees between the NPC and me. But that also complicates things. And with many NPCs I may end up with a lot of boxes again. Maybe I just reduce gun range to something that I can cover with collision boxes entirely in a reasonable time.

Maybe I was too ambitious with the size of the terrain.

A further solution would be: temporarily color-code the NPCs
(or a bounding box), then render to texture, then check whether A: any NPC can be seen and B: whether one was under the crosshair while the gun was shot. rendering this as a cubemap would allow also to check whether the NPCs can see you. Well, this idea is pretty weird, but you see I just do some brain storming.


csp-games
Guest
Quote
2022-02-16 05:27:21

latest status:
I successfully loaded tree position data from URL, cloned 1200 boxes and scaled and positioned them accordingly. framerate 2 fps ^^. I noticed, when boxes were set invisible, collision stopped working (to my surprise, I thought it's perfectly possible to have an invisible collision mesh??)

I then added a function that would hide all boxes that are not near the player, every 500ms. In order to have collision and transparency, I used a completely transparent alpha texture.

Collision with player works nicely at good speed, but interestingly, the line-collision-with-world function does ignore these boxes, despite them having working collision. Also, for visual control I set this transparent texture material to solid, and surprisingly it appeared for a brief moment black, but then became transparent - in solid material mode - weird.
So, the actual shooting check still doesn't work, as the line ignores these collision boxes. Why?!?

It's just another case of "the word easy doesn't exist in this api".


csp-games
Guest
Quote
2022-02-16 05:36:02

just in case you're interested, here's the code:



// before first drawing: ----------------------------------------
// reads a file from a URL into an array, then splits it up into an array of lines
// please note, the data processing is not executed right in the function call, but later, once the file was loaded.
// To access the data, you have to check whether it is actually loaded, eg. by setting a global variable to 1.
fetch("copperlichtdata/treepositions_data.dta")
.then(response => response.text())
.then( data => {
// here we can process the data
// alert(data);
// alert(data.length);
const mydata=data.split("\n"); // split at linebreaks
// alert(mydata[0]); // show 1st line
mtreex=new Array();
mtreey=new Array();
mtreez=new Array();
mtreer=new Array();
mtreecoll=new Array();
var anz=parseInt(mydata[1]); // number of trees
var collbox = ccbGetSceneNodeFromName("collbox");

for(i=0;i<anz;i++){
mtreex[i]=parseFloat(mydata[ 2+(i*5) ])-500;
mtreey[i]=parseFloat(mydata[ 2+(i*5)+1 ]);
mtreez[i]=parseFloat(mydata[ 2+(i*5)+2 ])-500;
mtreer[i]=parseFloat(mydata[ 2+(i*5)+3 ]);
mtreecoll[i]=ccbCloneSceneNode(collbox);
ccbSetSceneNodeProperty(mtreecoll[i],"Position",mtreex[i],mtreey[i],mtreez[i] );
//ccbSetSceneNodeProperty(mtreecoll[i],"Collision",true );
//ccbSetSceneNodeProperty(mtreecoll[i],"Visible",false );
}
ccbSetCopperCubeVariable("tree_c", anz);
} );



// every 500 ms -------------------------------------------------------

if(ccbGetCopperCubeVariable("tree_c") != 0){
var startPos3D = ccbGetSceneNodeProperty(ccbGetActiveCamera(), "Position");

var anz=ccbGetCopperCubeVariable("tree_c");
var maxdist=40;
for(i=0;i<anz;i++){
dx=Math.abs(startPos3D.X - mtreex[i]);
dy=Math.abs(startPos3D.Y - mtreey[i]);
dz=Math.abs(startPos3D.Z - mtreez[i]);
manhattan=(dx+dy+dz);
if(manhattan<maxdist){ccbSetSceneNodeProperty(mtreecoll[i],"Visible",true );}
else {ccbSetSceneNodeProperty(mtreecoll[i],"Visible",false );}
}
}






just_in_case
Moderator
Quote
2022-02-16 06:44:57

Did you try using Transparent additive material with a black solid texture for the boxes? and It's strange, in CC collision stay there even if the object is hidden(invisible) so there is probably something weird going on there, in order to update the collision one has to scale down the object to (0,0,0) and use the command ccbUpdatePhysicsGeometry() or have to move the hidden object somewhere else in the world position.

So if a collision is not working on hidden objects in your WebGL game, then probably the collision is handled in a different manner in your game than CC's native method.
As you have posted your issue regarding the Collision not working with the cloned meshes, it might have to do something with that, just for debugging purposes can you try doing a line check and collision check of the player with a non-cloned version of the collision box.
just add a simple native cube with Collision enabled in your game, and hide or unhide and check if it also disables the collision for the cube mesh. If it doesn't disable it then it's the problem with the collision of cloned meshes.

Regarding the weird issue that you are talking about the solid material mode, I highly, doubt that they didn't switch to transparent mode, instead they were hidden by the code, and become invisible. You might have the collision enabled for them, cause as I said collision doesn't suppose to be disabled when an object is hidden, so there is a probablity there is something wierd going on in there, that does hide the cubemeshes and there collision remains there, but there is this strange issue too, where it hides the cubemesh and the collision went away with it as well.

I think you should not use hide and unhide, instead try to use move to the position of the tree from the array.
capture the position of all the trees in the radius of the player into an array, and then according to the length of the array, create clones and position them to the tree positions capture in the array. Creates collision clones only once, and then reuse them by position already created collision box, according to the updated tree positions array.

That might help with the Collision issue.


just_in_case
Moderator
Quote
2022-02-16 07:01:23

I did something similar in my Shader, where I captured all the light in a scene into an array, and then according to the object radius I created an additional array of light nodes that need to be captured, as my shader can render up to 5 lights max, I was creating an array of 5 lights that are in the radius of the object. and then pass the array to the shader to update the light nodes, so now whenever the character moves and if there are more than 5 lights in the scene it captures the light nodes that are in the array and use them, and if the player moves somewhere else and the light stays behind the specified radius then it will automatically grab the next light into the array and feed that to the shader. that's how the automatic light grabbing is happening in my shader.

you can do something similar with your Collision boxes too.


csp-games
Guest
Quote
2022-02-16 17:54:38

Thanks you very much, just_in_case, it is very generous of you to spend so much time in helping me here. This is a great day, just on the radio mask mandates will fall tomorrow, and also this problem here I just solved.

First of all, there's a bad error in my code, that most likely was responsible for a lot of the strange behavior.
Note:
startPos3D.X etc is wrong !!!

it must be lower vase x: startPos3D.x , and y,z respectively! This was just returning NaN, messing things up, and the distance check to the camera.

Also, I have altered the above code in that it won't create a box clone for every tree anymore (while speed is ok when most of them are hidden, it's still hugging the RAM). Now I use a contingent of only 20 boxes that are dynamically positioned around the nearest trees, which is sufficient. Also, hiding and unhiding seems to work now, and maybe I can even make their collision work when they are hidden, which I still got to test.

So now I can shoot at a tree and the test projectile sticks to the tree (actually to the invisible box that is shaped like the stem). This means I can hide behind a nearby tree and an NPC is not able to see or shoot me. On the other hand, I can shoot an NPC that is hiding behind a distant tree - seems kind of unfair, well let's just call it a feature ^^

NPC AI will most likely be in a way that they would rather seek for visual contact to shoot the player, than to take cover, so it may not be that important.

It's amazing how much more organic a walktrough becomes, when you bump into a tree once in a while. So:
Collision: check. Shooting: check.

Thanks again.


csp-games
Guest
Quote
2022-02-16 18:17:29

Here again the sourcecode, two behaviors attached to the root scene node, one is "before first drawing", the other every 500 ms.
corrected, working version:

// ------------------------------------- before 1st drawing (also check "on reload")
ccbSetCopperCubeVariable("tree_c",0);
var conti=20;
ccbSetCopperCubeVariable("tree_conti",conti);
fetch("copperlichtdata/treepositions_data.dta")
.then(response => response.text())
.then( data => {
// here we can process the data
// alert(data);
// alert(data.length);
const mydata=data.split("\n"); // split at linebreaks
// alert(mydata[0]); // show 1st line
mtreex=new Array();
mtreey=new Array();
mtreez=new Array();
mtreer=new Array();
mtreecoll=new Array();
var anz=parseInt(mydata[1]);
var collbox = ccbGetSceneNodeFromName("collbox");

for(i=0;i<anz;i++){
mtreex[i]=parseFloat(mydata[ 2+(i*5) ])-500;
mtreey[i]=parseFloat(mydata[ 2+(i*5)+1 ]);
mtreez[i]=parseFloat(mydata[ 2+(i*5)+2 ])-500;
mtreer[i]=parseFloat(mydata[ 2+(i*5)+3 ]);
}
conti=ccbGetCopperCubeVariable("tree_conti");
for(i=0 ; i<conti ; i++){
mtreecoll[i]=ccbCloneSceneNode(collbox);

ccbSetSceneNodeProperty(mtreecoll[i],"Position",i*10,-2500,0 );
}
ccbSetCopperCubeVariable("tree_c", anz);
} );


//------------------------------------- every 500 ms

if(ccbGetCopperCubeVariable("tree_c") != 0){
var startPos3D =
ccbGetSceneNodeProperty(ccbGetActiveCamera(), "Position");

var anz=ccbGetCopperCubeVariable("tree_c");
var maxdist=40;
var coco=0;
var conti=ccbGetCopperCubeVariable("tree_conti");
for(i=0;i<anz;i++){
var dx=Math.abs(startPos3D.x - mtreex[i]);
var dy=Math.abs(startPos3D.y - mtreey[i]);
var dz=Math.abs(startPos3D.z - mtreez[i]);
var manhattan=(dx+dy+dz);
if(manhattan<maxdist){
if(coco<conti){
ccbSetSceneNodeProperty(mtreecoll[coco],"Position",mtreex[i],mtreey[i],mtreez[i]);
coco++;
} // from: if we still got contingent boxes to position?
} // from if tree is near
// else { } // not near

} // next i
} // from if data ready



Note, also turn on the "also on reload" feature for the before-1st-drawing behavior, otherwise it will work only every other time you run it - kinda funny.


just_in_case
Moderator
Quote
2022-02-17 03:32:32

Awesome that now the shooting and collision work. and Thanks again for sharing the Code itself, As you already know I am not into webGL that much but it will surely help many other fellow members, and maybe I will use it myself in the future when I planned to dive into the world of webGL.
Cheers!!


csp-games
Guest
Quote
2022-02-24 12:16:15

Thanks! The above code is in particular useful because it contains an example on how to load a text file and extract game parameters. It works in the browser, but the text file of course must be on a server, like on the same server or just inside the games' copperlichtdata folder.
Cheers!! ^^


Create reply:


Posted by: (you are not logged in)


Enter the missing letter in: "Inter?ational" (you are not logged in)


Text:

 

  

Possible Codes


Feature Code
Link [url] www.example.com [/url]
Bold [b]bold text[/b]
Image [img]http://www.example.com/image.jpg[/img]
Quote [quote]quoted text[/quote]
Code [code]source code[/code]

Emoticons


   






Copyright© Ambiera e.U. all rights reserved.
Privacy Policy | Terms and Conditions | Imprint | Contact