I'm trying to use this procedure for collision handling of my fps-camera.
It works nicely in general! But when I try to use it for a FPS-camera on a moving object (a ship), then it fails some times.
The camera is a child of the ship model, so it follows the ships movement, so maybe the sweepAndSlide procedure uses absolute vectors which causes the camera to jump over obstacles when the ship is rolling/pitching?
Any idea what to change to make it work with local vectors?
I do not need the camera to move in the Y direction, only X and Z, so maybe it can be made 2 dimensional?
Kind regards,
Daniel
procedureTForm1.SphereSweepAndSlide(freeform:TGLFreeform;SphereStart:TVector;varVelocity,newPosition:TVector;SphereRadius:Single);varoldPosition,ray:TVector;vel,slidedistance:Single;intPoint,intNormal:TVector;newDirection,newRay,collisionPosition,pointOnSphere,point2OnSphere:TVector;i:integer;CollisionState:TCollisionState;NegNormalizedVelocity:TVector;beginoldPosition:=SphereStart;//Directionsphereismovinginray:=VectorSubtract(newPosition,oldPosition);//ray:=Velocity;//newPosition:=VectorAdd(newPosition,ray);//Speedofspherevel:=VectorLength(ray);//iftheSphereisnotmoving,nothingisrequired//elsedoupto7loopsifvel>0thenfori:=0to6dobegin//ifanintersectionoccurs,willneedtodofurthercalculationsif(freeform.OctreeSphereSweepIntersect(oldPosition,ray,vel,SphereRadius,@intPoint,@intNormal))thenbeginifVectorDistance2(oldPosition,intPoint)<=sqr(SphereRadius)thenbegin//sphereisintersectingtriangleintNormal:=VectorScale(VectorSubtract(oldPosition,intPoint),1.0001);endelsebegin//sphereisnotintersectingtriangle//intNormal:=VectorSubtract(oldPosition,intPoint);//notcorrectbutworksokayatsmalltimesteps//intNormal:=VectorScale(VectorNormalize(intNormal),SphereRadius+0.0001);ifRayCastSphereIntersect(intPoint,VectorNormalize(VectorNegate(ray)),oldPosition,SphereRadius,PointOnSphere,Point2OnSphere)>0thenintNormal:=VectorScale(VectorSubtract(oldPosition,PointOnSphere),1.0001)//intNormal:=VectorScale(VectorNormalize(VectorSubtract(oldPosition,PointOnSphere)),SphereRadius+0.001)//VectorDistance(oldPosition,PointOnSphere));elsebegin//Assert(False);//thisshouldn't happen (this is here for debugging) intNormal:=VectorScale(VectorSubtract(oldPosition,intPoint),1.0001); end; end; //calculate position of centre of sphere when collision occurs collisionPosition:=VectorAdd(intPoint,intNormal); oldPosition:=collisionPosition; //calculate distance that wasn'ttravelled,duetoobstaclenewRay:=VectorSubtract(newPosition,collisionPosition);//calculatenewdirectionwhenawallishit(couldaddbouncingtothis)newDirection:=VectorCrossProduct(intNormal,VectorCrossProduct(newRay,intNormal));ifVectorNorm(NewDirection)>0thenNormalizeVector(newDirection);//calculatedistancethatitshouldslide(dependsonanglebetweenplane&ray)SlideDistance:=vectorDotProduct(newRay,newDirection);//stillneedtoimplementfrictionproperly//ifabs(SlideDistance)<10*deltaTimethenSlideDistance:=0;ScaleVector(newDirection,SlideDistance);//calculatenewpositionsphereisheadingtowardsnewPosition:=VectorAdd(collisionPosition,newDirection);ray:=newDirection;vel:=VectorLength(ray);{//displayarrowsforcollisionnormals&slidedirectionifi=0then//DrawArrows(intPoint,intNormal,Ray,GLArrowLine1,GLArrowLine4)elseifi=1then//DrawArrows(intPoint,intNormal,Ray,GLArrowLine2,GLArrowLine5)elseifi=2then//DrawArrows(intPoint,intNormal,Ray,GLArrowLine3,GLArrowLine6)elseifi=6thenbegin//caption:=FloatToStr(vectordistance(newPosition,oldPosition));newPosition:=oldPosition;break;end;}//checkifverysmallmotion(e.g.whenstuckinacorner)ifvel<1E-10then//deltaTimethenbeginnewPosition:=oldPosition;break;end;{CollisionState:=TCollisionState.Create();CollisionState.Position:=oldPosition;CollisionState.Contact.intNormal:=intNormal;CollisionState.Contact.intPoint:=intPoint;CollisionState.Time:=GetTickCount64();CollisionStates.Add(CollisionState);}endelse//nocollisionoccured,soquitloopbeginBreak;end;end;//endiloopVelocity:=Ray;end;
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
I found my problem as well as a simple solution for the local issue!
First of all I used Scale instead of autoScaling for the model, this seems to have made "holes" in the freeForm.
Secondly I let the collision model stay at postion 0,0,0 and use global position vectors, while my camera onboard the moving ship uses local position vectors. Then when I move onboard the ship, a sphere is moving inside the global collision model and my camera gets it's position from the sphere.
So player local position := collision Spheres global position.
Cheers!
If you would like to refer to this comment somewhere else in this project, copy and paste the following link:
Hello everyone!
I'm trying to use this procedure for collision handling of my fps-camera.
It works nicely in general! But when I try to use it for a FPS-camera on a moving object (a ship), then it fails some times.
The camera is a child of the ship model, so it follows the ships movement, so maybe the sweepAndSlide procedure uses absolute vectors which causes the camera to jump over obstacles when the ship is rolling/pitching?
Any idea what to change to make it work with local vectors?
I do not need the camera to move in the Y direction, only X and Z, so maybe it can be made 2 dimensional?
Kind regards,
Daniel
Hi gents!
I found my problem as well as a simple solution for the local issue!
First of all I used Scale instead of autoScaling for the model, this seems to have made "holes" in the freeForm.
Secondly I let the collision model stay at postion 0,0,0 and use global position vectors, while my camera onboard the moving ship uses local position vectors. Then when I move onboard the ship, a sphere is moving inside the global collision model and my camera gets it's position from the sphere.
So player local position := collision Spheres global position.
Cheers!