Slothman Posted July 17, 2011 Share Posted July 17, 2011 I am need of a way that a client could calculate the angles of a surface. i need to be able to take 2 xyz coords and detect if an object is between them (easy so far using processlineofsight) but if there is something blocking the line, then i need to know its surface angle. I imagine this would be done by measuring the coords of 3 or 4 parralell lines of sight and using them to calculate the angle of the item. this is where im stuck. I threw together this diagram to help you see what i mean: keep in mind it needs to be 3d, not 2d, and the angles would be needed for placing objects. any pointing in the right direction would be appreciated from any math whizzes Link to comment
Uisaqin Posted July 18, 2011 Share Posted July 18, 2011 what about using 2 of these functions https://wiki.multitheftauto.com/wiki/Useful_Functions something like function getLineHitAngle(Point1X, Point1Y, Point1Z, Point2X, Point2Y, Point2Z) local Hit, HitX, HitY, HitZ = processLineOfSight(Point1X, Point1Y, Point1Z, Point2X, Point2Y, Point2Z) if Hit then local LineAngle = findRotation(Point1X, Point1Y, Point2X, Point2Y) local LineDistance = 2 local Point3X, Point3Y = getPointFromDistanceRotation(Point1X, Point1Y, LineDistance, LineAngle - 90) local Point4X, Point4Y = getPointFromDistanceRotation(Point2X, Point2Y, LineDistance, LineAngle - 90) local Hit2, Hit2X, Hit2Y, Hit2Z = processLineOfSight(Point3X, Point3Y, Point1Z, Point4X, Point4Y, Point2Z) if Hit2 then return findRotation(HitX, HitY, Hit2X, Hit2Y) - LineAngle end end return false end Link to comment
Slothman Posted July 18, 2011 Author Share Posted July 18, 2011 thanks, that really got me started. It'll need some back up parts for when the calculations dont make sense (like a player aims too close to a corner) one of the uses for this is to update my grapple script, but this sort of calculation could be used to add things like bullet hole marks, spray tags, blood splatters, etc. so heres part of the script so far: function getPointFromDistanceRotation(x, y, dist, angle) local a = math.rad(90 - angle); local dx = math.cos(a) * dist; local dy = math.sin(a) * dist; return x+dx, y+dy; end function findRotation(x1,y1,x2,y2) local t = -math.deg(math.atan2(x2-x1,y2-y1)) if t < 0 then t = t + 360 end; return t; end grapplegun = 26 --WHICH GUN WILL BE USED AS A GRAPPLE? gunrange = 80 --HOW FAR WILL THE GRAPPLE RANGE BE? function onClientPlayerWeaponFireFunc(weapon, ammo, ammoInClip, hitX, hitY, hitZ, hitElement ) if weapon == grapplegun then if source == getLocalPlayer() then local Point1X, Point1Y, Point1Z = getPedTargetStart(getLocalPlayer()) local lx, ly, lz = getPedTargetEnd(getLocalPlayer()) local len = getDistanceBetweenPoints3D(Point1X, Point1Y, Point1Z, lx, ly, lz) local Point2X = Point1X + (lx - Point1X)/len*gunrange local Point2Y = Point1Y + (ly - Point1Y)/len*gunrange local Point2Z = Point1Z + (lz - Point1Z)/len*gunrange local Hit, HitX, HitY, HitZ = processLineOfSight(Point1X, Point1Y, Point1Z, Point2X, Point2Y, Point2Z) -- first line of sight if Hit then local LineAngle = findRotation(Point1X, Point1Y, Point2X, Point2Y) local LineDistance = .2 local Point3X, Point3Y = getPointFromDistanceRotation(Point1X, Point1Y, LineDistance, LineAngle - 90) local Point4X, Point4Y = getPointFromDistanceRotation(Point2X, Point2Y, LineDistance, LineAngle - 90) local Hit2, Hit2X, Hit2Y, Hit2Z = processLineOfSight(Point3X, Point3Y, Point1Z, Point4X, Point4Y, Point2Z) -- second line of sight, directly left if Hit2 then angle = findRotation(HitX, HitY, Hit2X, Hit2Y) end createObject ( 1318, HitX, HitY, HitZ ,90, 0, angle ) end end end end addEventHandler ( "onClientPlayerWeaponFire", getRootElement(), onClientPlayerWeaponFireFunc ) the problem with this is that it seems to jump 180 degrees when at certain angles. this would definitly be a problem for my purposes. any advice? Link to comment
Antibird Posted July 18, 2011 Share Posted July 18, 2011 In case 1.1 is in use, processLineOfSight( ) has 3 nice variables to return, which are normalX, normalY, normalZ ( nothing else, but a surface normal ). To have 6 points is just enough to get angles you need, using getPointFromDistanceRotation( ) as been supposed. This basically makes it possible to cast 1 ray instead of 2. Link to comment
eAi Posted July 18, 2011 Share Posted July 18, 2011 You need to cast a minimum of three rays, I think there are some edge cases that would require more. You need to cast three rays with the same direction, in a triangle - let's call them rays A, B and C. The angle ABC should be at 90 degrees along the direction of the ray. Assuming all three rays hit, you should calculate the vectors B -> A and B -> C Normalize those vectors. Cross product those two vectors. You should have the surface's normal. You'll have problems if one vector doesn't hit (the very edge of an object) and also at the intersection of two objects, but if you make the distance between the rays as small as possible, you shouldn't really notice this. It also won't work at very acute angles. Or just wait for 1.1 Link to comment
qaisjp Posted July 19, 2011 Share Posted July 19, 2011 I don't know whether this may help or not, but on The_GTA's testing server there is a resource called "surface" and I asked what it was and he claims it's a default resource. I havnt seen if it is, but if it isn't I will try and get it and post it on here. Link to comment
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now