Raised This Month: $ Target: $400
 0% 

Point inclusion, Zone points generation, and Zone drawing


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
blaacky
Senior Member
Join Date: Oct 2012
Old 08-06-2013 , 22:47   Point inclusion, Zone points generation, and Zone drawing
Reply With Quote #1

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];
        }
    }

__________________

Last edited by blaacky; 06-14-2017 at 18:53.
blaacky is offline
shavit
AlliedModders Donor
Join Date: Dec 2011
Location: Israel
Old 08-15-2013 , 14:56   Re: Point inclusion, Zone points generation, and Zone drawing
Reply With Quote #2

The first one is so damn useful.
__________________
retired
shavit is offline
TnTSCS
AlliedModders Donor
Join Date: Oct 2010
Location: Undisclosed...
Old 08-15-2013 , 15:57   Re: Point inclusion, Zone points generation, and Zone drawing
Reply With Quote #3

This should be added to SMLib for sure
__________________
View my Plugins | Donate
TnTSCS is offline
Peace-Maker
SourceMod Plugin Approver
Join Date: Aug 2008
Location: Germany
Old 08-27-2013 , 07:11   Re: Point inclusion, Zone points generation, and Zone drawing
Reply With Quote #4

PHP Code:
if(point[0][i]>=playerPos[i] == point[7][i]>=playerPos[i]) 
That doesn't look right to me?
__________________
Peace-Maker is offline
Bimbo1
Senior Member
Join Date: Jan 2010
Location: brazil
Old 09-06-2013 , 01:16   Re: Point inclusion, Zone points generation, and Zone drawing
Reply With Quote #5

Quote:
Originally Posted by Peace-Maker View Post
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!
__________________
sie sind das essen und wir sind die jäger!

Last edited by Bimbo1; 09-06-2013 at 01:20. Reason: i'm dumb.
Bimbo1 is offline
floube
SourceMod Donor
Join Date: Jan 2013
Location: Austria
Old 08-28-2013 , 14:24   Re: Point inclusion, Zone points generation, and Zone drawing
Reply With Quote #6

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;


Last edited by floube; 08-28-2013 at 14:28.
floube is offline
friagram
Veteran Member
Join Date: Sep 2012
Location: Silicon Valley
Old 09-07-2013 , 03:40   Re: Point inclusion, Zone points generation, and Zone drawing
Reply With Quote #7

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
__________________
Profile - Plugins
Add me on steam if you are seeking sp/map/model commissions.
friagram is offline
Bimbo1
Senior Member
Join Date: Jan 2010
Location: brazil
Old 09-07-2013 , 04:45   Re: Point inclusion, Zone points generation, and Zone drawing
Reply With Quote #8

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?
__________________
sie sind das essen und wir sind die jäger!
Bimbo1 is offline
blaacky
Senior Member
Join Date: Oct 2012
Old 09-07-2013 , 15:50   Re: Point inclusion, Zone points generation, and Zone drawing
Reply With Quote #9

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.
blaacky is offline
friagram
Veteran Member
Join Date: Sep 2012
Location: Silicon Valley
Old 09-08-2013 , 14:04   Re: Point inclusion, Zone points generation, and Zone drawing
Reply With Quote #10

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.
__________________
Profile - Plugins
Add me on steam if you are seeking sp/map/model commissions.

Last edited by friagram; 09-08-2013 at 14:15.
friagram is offline
Reply



Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


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


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