AlliedModders

AlliedModders (https://forums.alliedmods.net/index.php)
-   Snippets and Tutorials (https://forums.alliedmods.net/forumdisplay.php?f=112)
-   -   Point inclusion, Zone points generation, and Zone drawing (https://forums.alliedmods.net/showthread.php?t=222822)

blaacky 08-06-2013 22:47

Point inclusion, Zone points generation, and Zone drawing
 
The logic is in there and the code is pretty short. It just checks if a player is between two opposite corners of a zone in all 3 axes. It would be neat in the future to have this work so it checks if any single part of a character is within a zone and not just the center of their feet.
PHP Code:

/*
* returns true if a player is inside the given zone
* returns false if they aren't in it
*/
bool:IsInsideZone(clientFloat:point[8][3])
{
    new 
Float:playerPos[3];
    
    
GetEntPropVector(clientProp_Send"m_vecOrigin"playerPos);
    
playerPos[2] += 5.0;
    
    for(new 
i=0i<3i++)
    {
        if(
point[0][i]>=playerPos[i] == point[7][i]>=playerPos[i])
        {
            return 
false;
        }
    }

    return 
true;


Here is a function I use to draw a zone
PHP Code:

/*
* Graphically draws a zone
*    if client == 0, it draws it for all players in the game
*   if client index is between 0 and MaxClients+1, it draws for the specified client
*/
DrawZone(clientFloat:array[8][3], beamspritehalospritecolor[4], Float:life)
{
    for(new 
i=0i2=3i2>=0i+=i2--)
    {
        for(new 
j=1j<=7j+=(j/2)+1)
        {
            if(
!= 7-i)
            {
                
TE_SetupBeamPoints(array[i], array[j], beamspritehalosprite00life5.05.000.0color0);
                if(
client <= MaxClients)
                    
TE_SendToClient(client0.0);
                else
                    
TE_SendToAll(0.0);
            }
        }
    }


And here is one I use to generate all 8 zone points from 2 opposite corners. This is so the zone can be drawn
PHP Code:

/*
* Generates all 8 points of a zone given just 2 of its points
*/
CreateZonePoints(Float:point[8][3])
{
    for(new 
i=1i<7i++)
    {
        for(new 
j=0j<3j++)
        {
            
point[i][j] = point[((>> (2-j)) & 1) * 7][j];
        }
    }



shavit 08-15-2013 14:56

Re: Point inclusion, Zone points generation, and Zone drawing
 
The first one is so damn useful.

TnTSCS 08-15-2013 15:57

Re: Point inclusion, Zone points generation, and Zone drawing
 
This should be added to SMLib for sure :)

Peace-Maker 08-27-2013 07:11

Re: Point inclusion, Zone points generation, and Zone drawing
 
PHP Code:

if(point[0][i]>=playerPos[i] == point[7][i]>=playerPos[i]) 

That doesn't look right to me?

floube 08-28-2013 14:24

Re: Point inclusion, Zone points generation, and Zone drawing
 
This should be useful aswell :)

PHP Code:

/**
 * Checks if two zones intersect (overlap).
 *
 * @param fCheck        First zone (8 given points).
 * @param fSource       Second zone (8 given points).
 * @return              True if they intersect, false otherwise.
 */

stock bool:ZonesIntersect(Float:fCheck[8][3], Float:fSource[8][3]) {
    if (
fCheck[0][0] > fSource[4][0] ||    // fCheck is right of fSource
        
fCheck[4][0] < fSource[0][0] ||    // fCheck is left of fSource
        
fCheck[1][2] < fSource[0][2] ||    // fCheck is below fSource
        
fCheck[0][2] > fSource[1][2] ||    // fCheck is above fSource
        
fCheck[3][1] < fSource[1][1] ||    // fCheck is behind fSource
        
fCheck[1][1] > fSource[3][1]) {    // fCheck is in front fSource
        
return false;
    }

    return 
true;



Bimbo1 09-06-2013 01:16

Re: Point inclusion, Zone points generation, and Zone drawing
 
Quote:

Originally Posted by Peace-Maker (Post 2022498)
PHP Code:

if(point[0][i]>=playerPos[i] == point[7][i]>=playerPos[i]) 

That doesn't look right to me?

yeah, that's weird, but right.
Code:

(point[0][i]>=playerPos[i]) == (point[7][i]>=playerPos[i])
if the condition is true for both, then the player(or, better saying, the point) can't be inside the zone.

i tried to do some things. i'm not really sure if it works, i barely tested it with some barrels at dust2.
also, i'm not sure if it's the best way to do that things. i didn't really know how to do that, so i did some terrible drafts on photoshop and it seemed far away that it would be possible to be done. anyways, it's probably a bad method for calculating these things. i wonder how people do it out there in real life.
Code:

#include <sourcemod>
#include <cstrike>
#include <sdktools>
#include <smlib>
#include <sdkhooks>

#pragma semicolon 1

new const Float:NULLBOXPOINTS[8][3] = {{0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}, {0.0, 0.0, 0.0}};
new const Float:ZERO_VECTOR[3] = {0.0, 0.0, 0.0};


Float:setupentitysphere(ent, const Float:addmin[3], const Float:addmax[3], Float:origin[3]){

        decl Float:min[3], Float:max[3];
        Entity_GetMinSize(ent, min);
        AddVectors(min, addmin, min);
        Entity_GetMaxSize(ent, max);
        AddVectors(max, addmax, max);
        Entity_GetAbsOrigin(ent, origin);
        decl Float:vec[3];
        SubtractVectors(max, min, vec);
        ScaleVector(vec, 0.5);
        AddVectors(origin, min, origin);
        AddVectors(origin, vec, origin);
        return SquareRoot(GetVectorDotProduct(vec, vec));

}

bool:collidespheres(const Float:origin1[3], const Float:radius1, const Float:origin2[3], const Float:radius2){

        if(GetVectorDistance(origin1, origin2) <= radius1+radius2){

                return true;

        }else{

                return false;

        }


}

makeortonormalbase(const Float:points[8][3], Float:base[3][3], Float:bounds[3]){

        SubtractVectors(points[1], points[0], base[0]);
        SubtractVectors(points[2], points[0], base[1]);
        SubtractVectors(points[4], points[0], base[2]);
        new Float:norma = SquareRoot(GetVectorDotProduct(base[0], base[0]));
        bounds[0] = norma;
        ScaleVector(base[0], 1/norma);

        norma = SquareRoot(GetVectorDotProduct(base[1], base[1]));
        bounds[1] = norma;
        ScaleVector(base[1], 1/norma);

        norma = SquareRoot(GetVectorDotProduct(base[2], base[2]));
        bounds[2] = norma;
        ScaleVector(base[2], 1/norma);

}

bool:arepointsinsidebox(const Float:points1[8][3], const Float:base[3][3], const Float:length[3], const Float:points2[8][3]){

        for(new i = 0; i < 7; i++){

                decl Float:vec[3];
                copyvector(points2[i], vec);
                SubtractVectors(vec, points1[0], vec);
                if(ispointinsidebox(base, length, vec)){

                        return true;

                }else{

                        continue;

                }

        }
        return false;

}

bool:ispointinsidebox(const Float:base[3][3], const Float:length[3], const Float:point[3]){

        for(new i = 0; i < 3; i++){

                new Float:thedotproduct = GetVectorDotProduct(point, base[i]);
                if(thedotproduct > length[i] || thedotproduct < 0.0){

                        return false;

                }

        }
        return true;

}

intersectboxes(const Float:points1[8][3], const Float:points2[8][3]){

        decl Float:ortonormalbase1[3][3];
        decl Float:bounds1[3];
        makeortonormalbase(points1, ortonormalbase1, bounds1);

        decl Float:ortonormalbase2[3][3];
        decl Float:bounds2[3];
        makeortonormalbase(points2, ortonormalbase2, bounds2);

        if(arepointsinsidebox(points1, ortonormalbase1, bounds1, points2) || arepointsinsidebox(points2, ortonormalbase2, bounds2, points1)){

                return true;

        }else if(intersectplanewithbox(points1[0], points1[1], points1[2], points2) ||
        intersectplanewithbox(points1[1], points1[3], points1[5], points2) ||
        intersectplanewithbox(points1[5], points1[4], points1[7], points2) ||
        intersectplanewithbox(points1[6], points1[7], points1[2], points2) ||
        intersectplanewithbox(points1[6], points1[2], points1[4], points2) ||
        intersectplanewithbox(points1[5], points1[1], points1[4], points2)){

                return true;


        }else{

                return false;

        }

}

intersectplanewithbox(const Float:point1[3], const Float:point2[3], const Float:point3[3], const Float:box[8][3]){

        if(intersectplaneandline(point1, point2, point3, box[0], box[1]) ||
        intersectplaneandline(point1, point2, point3, box[0], box[2]) ||
        intersectplaneandline(point1, point2, point3, box[2], box[3]) ||
        intersectplaneandline(point1, point2, point3, box[1], box[3]) ||
        intersectplaneandline(point1, point2, point3, box[0], box[4]) ||
        intersectplaneandline(point1, point2, point3, box[1], box[5]) ||
        intersectplaneandline(point1, point2, point3, box[2], box[6]) ||
        intersectplaneandline(point1, point2, point3, box[3], box[7]) ||
        intersectplaneandline(point1, point2, point3, box[4], box[5]) ||
        intersectplaneandline(point1, point2, point3, box[4], box[6]) ||
        intersectplaneandline(point1, point2, point3, box[6], box[7]) ||
        intersectplaneandline(point1, point2, point3, box[5], box[7])){

                return true;

        }else{

                return false;

        }

}

setupentityzone(ent, bool:shoulddraw = false, const Float:addmin[3] = ZERO_VECTOR, const Float:addmax[3] = ZERO_VECTOR, Float:points[8][3] = NULLBOXPOINTS){

        decl Float:min[3], Float:max[3];
        decl Float:angles[3], Float:origin[3];
        Entity_GetMinSize(ent, min);
        AddVectors(min, addmin, min);
        Entity_GetMaxSize(ent, max);
        AddVectors(max, addmax, max);
        Entity_GetAbsAngles(ent, angles);
        Entity_GetAbsOrigin(ent, origin);
       
        for(new i = 0; i < 3; i++){

                angles[i] = DegToRad(angles[i]);

        }
        CreateZonePoints(origin, min, max, angles, points);
        if(shoulddraw){

                DrawZone(0, points, bsprite, hsprite, {255, 0, 0, 255}, 3.0);

        }

}

bool:intersectplaneandline(const Float:plane_rightpoint[3], const Float:plane_point2[3], const Float:plane_point3[3], Float:line_point1[3], Float:line_point2[3]){


        decl Float:plane_vec1[3];
        SubtractVectors(plane_point2, plane_rightpoint, plane_vec1);
        new Float:height = SquareRoot(GetVectorDotProduct(plane_vec1, plane_vec1));
        ScaleVector(plane_vec1, 1/height);
        decl Float:plane_vec2[3];
        SubtractVectors(plane_point3, plane_rightpoint, plane_vec2);
        new Float:width = SquareRoot(GetVectorDotProduct(plane_vec2, plane_vec2));
        ScaleVector(plane_vec2, 1/width);

        decl Float:vec[3];
        decl Float:vecline[3];
        SubtractVectors(line_point1, plane_rightpoint, vecline);
        copyvector(plane_vec1, vec);
        ScaleVector(vec, GetVectorDotProduct(vecline, plane_vec1));
        decl Float:projection[3];

        copyvector(vec, projection);

        copyvector(plane_vec2, vec);
        ScaleVector(vec, GetVectorDotProduct(vecline, plane_vec2));
        AddVectors(vec, projection, projection);


        decl Float:distancevector1[3];
        SubtractVectors(vecline, projection, distancevector1);

        SubtractVectors(line_point2, plane_rightpoint, vecline);

        copyvector(plane_vec1, vec);
        ScaleVector(vec, GetVectorDotProduct(vecline, plane_vec1));
        decl Float:projection2[3];
        copyvector(vec, projection2);

        copyvector(plane_vec2, vec);
        ScaleVector(vec, GetVectorDotProduct(vecline, plane_vec2));
        AddVectors(vec, projection2, projection2);

        decl Float:distancevector2[3];

       
        SubtractVectors(vecline, projection2, distancevector2);

        new Float:distancevector1module = SquareRoot(GetVectorDotProduct(distancevector1, distancevector1));
        new Float:distancevector2module = SquareRoot(GetVectorDotProduct(distancevector2, distancevector2));

        new Float:distancebetweenprojections = GetVectorDistance(projection, projection2);

       
        if(GetVectorDotProduct(distancevector1, distancevector2) >= 0){

                return false;

        }else{

                decl Float:vecbetweenprojections[3];
                SubtractVectors(projection2, projection, vecbetweenprojections);
                ScaleVector(vecbetweenprojections, 1/SquareRoot(GetVectorDotProduct(vecbetweenprojections, vecbetweenprojections)));
                ScaleVector(vecbetweenprojections, distancebetweenprojections*distancevector1module/(distancevector1module+distancevector2module));
                decl Float:intersectpoint[3];
                AddVectors(projection, vecbetweenprojections, intersectpoint);

               
                return intersectpointinsquare(plane_vec1, height, plane_vec2, width, intersectpoint);

        }


}

bool:intersectpointinsquare(const Float:plane_vec1[3], const Float:height, const Float:plane_vec2[3], const Float:width, Float:point[3]){

        new Float:productbetweenvec1andpoint = GetVectorDotProduct(plane_vec1, point);
        new Float:productbetweenvec2andpoint = GetVectorDotProduct(plane_vec2, point);
        if(productbetweenvec1andpoint >= 0 && productbetweenvec1andpoint <= height && productbetweenvec2andpoint >= 0 && productbetweenvec2andpoint <= width){

                return true;

        }else{

                return false;

        }

}

copyvector(const Float:vec1[3], Float:vec2[3]){

        vec2[0] = vec1[0];
        vec2[1] = vec1[1];
        vec2[2] = vec1[2];

}

//blaacky stuff which i ruined

/*
* Generates all 8 points of a zone given just 2 of its points
*/
CreateZonePoints(Float:origin[3], const Float:min[3], const Float:max[3], Float:ang[3], Float:point[8][3])
{

        decl Float:f1[3];
        decl Float:f2[3];

        new Float:ca = Cosine(ang[0]);
        new Float:sa = Sine(ang[0]);
        new Float:cb = Cosine(ang[1]);
        new Float:sb = Sine(ang[1]);
        new Float:cc = Cosine(ang[2]);
        new Float:sc = Sine(ang[2]);

        f1[0] = ca*cb;
        f1[1] = ca*sb;
        f1[2] = -sa;

        f2[0] = cc*sa*cb+sc*sb;
        f2[1] = cc*sa*sb-sc*cb;
        f2[2] = cc*ca;

        decl Float:f3[3];
        f3[0] = f1[1]*f2[2] - f1[2]*f2[1];
        f3[1] = f1[2]*f2[0] - f1[0]*f2[2];
        f3[2] = f1[0]*f2[1] - f1[1]*f2[0];


        decl Float:fminandmax[2][3][3];
        fminandmax[0][0][0] = f1[0]*min[1];
        fminandmax[0][0][1] = f1[1]*min[1];
        fminandmax[0][0][2] = f1[2]*min[1];
        fminandmax[0][1][0] = f2[0]*min[2];
        fminandmax[0][1][1] = f2[1]*min[2];
        fminandmax[0][1][2] = f2[2]*min[2];
        fminandmax[0][2][0] = f3[0]*min[0];
        fminandmax[0][2][1] = f3[1]*min[0];
        fminandmax[0][2][2] = f3[2]*min[0];
        fminandmax[1][0][0] = f1[0]*max[1];
        fminandmax[1][0][1] = f1[1]*max[1];
        fminandmax[1][0][2] = f1[2]*max[1];
        fminandmax[1][1][0] = f2[0]*max[2];
        fminandmax[1][1][1] = f2[1]*max[2];
        fminandmax[1][1][2] = f2[2]*max[2];
        fminandmax[1][2][0] = f3[0]*max[0];
        fminandmax[1][2][1] = f3[1]*max[0];
        fminandmax[1][2][2] = f3[2]*max[0];

        for(new i = 0; i < 8; i++){

                new Float:vec[3] = {0.0, 0.0, 0.0};
                for(new j = 0; j < 3; j++){

                        AddVectors(vec, fminandmax[((i >> (2-j)) & 1) * 1][j], vec);

                }
                AddVectors(vec, origin, point[i]);

        }
}


//this is the only part that stills neat, as i didn't touch it.
/*
* Graphically draws a zone
*        if client == 0, it draws it for all players in the game
*  if client index is between 0 and MaxClients+1, it draws for the specified client
*/
DrawZone(client, Float:array[8][3], beamsprite, halosprite, color[4], Float:life)
{
        for(new i=0, i2=3; i2>=0; i+=i2--)
        {
                for(new j=1; j<=7; j+=(j/2)+1)
                {
                        if(j != 7-i)
                        {
                                TE_SetupBeamPoints(array[i], array[j], beamsprite, halosprite, 0, 0, life, 5.0, 5.0, 0, 0.0, color, 0);
                                if(0 < client <= MaxClients)
                                        TE_SendToClient(client, 0.0);
                                else
                                        TE_SendToAll(0.0);
                        }
                }
        }
}

sorry if it's bad documented or not documented at all. it is still just drafts, it probably has a lot of bugs. but, well, here is a quick documentation about the most important functions:
setupentitysphere makes a sphere on an entity big enough to contains its mins and maxs. the value returned is the radius of the sphere. the mins and maxs can be changed with parameters.
collidespheres is used to check if two spheres are colliding or not.
setupentityzone makes a zone on an entity based on its mins and maxs, position and angles with CreateZonePoints. the mins and maxs can also be changed.
CreateZonePoints(credits to blaacky) makes a zone with the parameters origin, mins, maxs and angles.
intersectboxes is used to check whether two sets of zone points, which must be created with CreateZonePoints, setupentityzone or by something that uses a similar enough method, are colliding or not.

i know the spheres thing aren't zones(or is it?), but i find it cool to be used before zones calculations because they are much lighter than them(this sounded funny). and, i mean, if the spheres made out of two boxes aren't colliding, there is no way those two boxes would collide. that saves a lot of unnecessary calculations.

now, what really matters: blaacky, hunter x hunter is awesome! that last scene of your profile picture character in the manga was just soo, soooo... i won't say anything! it might be a spoiler for someone.
but arghhh, bro,why don't yoshihiro togashi release more hxh manga? i neeeed it! gon sz, killua sz, killua's sister sz, chimera ants blurghh, nothing personal, though. the story is getting just so interesting, but why won't yoshihiro write it!!??? he's too slow and lazy. urghjdioasjdiuosa.
i wish i could spend more time(and waste more of your time because you are reading this) saying how much i luv that anime/manga(and other animes/mangas too), but i can't, i have school and it's already too late. dang you, school!

friagram 09-07-2013 03:40

Re: Point inclusion, Zone points generation, and Zone drawing
 
For finding if a point is in a zone, Why not just subtract the mins from maxs and return the combined result... .
You dont have to use a loop and it completes much faster

Bimbo1 09-07-2013 04:45

Re: Point inclusion, Zone points generation, and Zone drawing
 
i didn't get it. how subtracting the mins from maxs of a zone would tell if a point is inside of it or not?

blaacky 09-07-2013 15:50

Re: Point inclusion, Zone points generation, and Zone drawing
 
The only other IsInsideZone functions I've seen are definitely not faster than this one. They tend to declare a lot of variables like highx, highy, highz, lowx, lowy, lowz and compare the player's position to all of those after getting them. I don't see how that's faster than 3 simple loops with an if that just checks some variables.

friagram 09-08-2013 14:04

Re: Point inclusion, Zone points generation, and Zone drawing
 
Well i store my zones in a trie (with mins being cell 0 1 2 and maxs being 3 4 5, but same idea:
If the point is outside the mins + maxs of all 3 bounds, it is not inside the zone..

PHP Code:

            inX = ( Coords[0] >= arry[0] && Coords[0] <= arry[3] );
            
inY = ( Coords[1] >= arry[1] && Coords[1] <= arry[4] );
            
inZ = ( Coords[2] >= arry[2] && Coords[2] <= arry[5] );

            if ( 
inX && inY && inZ )
            {
                return 
true;
            }

likewise:

            if ( ( 
Coords[0] >= arry[0] && Coords[0] <= arry[3] ) && Coords[1] >= arry[1] && Coords[1] <= arry[4] ) && Coords[2] >= arry[2] && Coords[2] <= arry[5] ) )
            {
                return 
true;
            } 

Here you need few variables, and it will return upon failure very quickly due to ands.


All times are GMT -4. The time now is 18:27.

Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.