samp.directory
← Scripts and libraries

imshooter/3DAndreas

An open.mp component for physics and map queries on San Andreas, built on Jolt Physics: rays, ground, sight, overlaps, water, surfaces, players, vehicles, actors and the screen.

Plugin★ 2updated yesterdayMITC++
Open on GitHub

README.md

3DAndreas

[!NOTE] 3DAndreas is experimental and already runs in production. Its natives may still change from one version to the next. It was made with Claude Opus 5.5, a model by Anthropic.

An open.mp component that simulates physics on the map of San Andreas with Jolt Physics and answers questions about that map: what a ray hits, where the ground is, whether two points see each other, what a shape overlaps, where the water lies and what a player has on screen. It loads from the components folder, is configured in config.json and reads the map from a database built from the files of the game.

Demo

Physics objects moved by 3DAndreas, recorded in the game on an open.mp server. The picture opens the video on YouTube.

Features

  • Physics objects. Spheres, boxes and objects shaped like a model fall, roll, bounce, float and push each other. Players see them as objects the component moves, with at most max_updates updates a second, so even a rain of hundreds of objects never floods a client. Static objects and zones never move and make walls, tables and goals.
  • Model settings. models.json gives the shape, mass, friction, bounce and more to 203 models, from balls to weapons, so A3D_CreateObject(1946, x, y, z) makes a basketball that bounces like one. Every other model gets a mass from its volume and a friction and bounce from what its collision is made of.
  • World queries. Rays give the point, the normal, the model and the surface of the game they hit. There are rays that return every hit, line of sight, ground height, sphere sweeps and the overlaps of a sphere, a box or a model.
  • Players, vehicles and actors. Players on foot and actors are capsules and vehicles are boxes that move with them, so objects bounce off them and queries find them. A player pushes a pile of crates the way a person would, without throwing them. Searches in a sphere or a cone can require line of sight, and the camera of a player gives what they look at.
  • The map. Water levels, points under water or inside the collision of the map, free spots on the ground, predicted throws, the size and the object.dat data of models, and building removal for every virtual world or for one.
  • The screen. Where a point of the world shows on the screen of a player, and what a point of the screen shows, in text draw units.
  • Geometry. The rotation that stands an object on a slope, reflections, offsets relative to objects and vehicles, the parts of a vehicle, and quaternions.

Compared with ColAndreas

The same queries on ColAndreas 1.5 and on 3DAndreas, measured with tests/colandreas.pwn on one computer:

ColAndreas 1.53DAndreas
Server ready after launch2.8 s0.47 s
Private memory of the server557 MB178 MB
10,000 rays of 100 metres70 ms16 ms
10,000 lines of sight70 ms14 ms
10,000 ground heights73 ms18 ms
1,000 rays that return every hit19 ms9 ms
1,000 contact tests7 ms2 ms

A bare server, with neither of them, is ready in 0.25 s and uses 51 MB. When rays stop at the water, as they do in ColAndreas, 113 of 120 ground heights across the map are identical and the other 7 lie within 5 mm.

Cost on the server

Each scenario of tests/stress.pwn ran for a minute on 3DAndreas 0.6.3, on one computer. The component column is the time A3D_GetStats reports on the thread of the server, and the whole server column is the CPU the process used on all its threads, bots and network included, both as a share of one core:

ScenarioComponent, share of one coreWhole server, share of one coreUpdates sent
A pool table, a shot every six seconds0.8%2.7%64 a second
Eight pool tables, a shot on each every six seconds1.8%5.6%405 a second
Waves of 100 objects thrown every ten seconds, 50 bots connected1.0%4.3%165 a second
500 boxes in an arena, 50 kicked every two seconds, 50 bots connected3.1%9.5%816 a second
The 500 boxes at rest0.06%1.3%none

Objects at rest cost almost nothing, so the cost follows the objects in motion, not the objects created. The same scenarios at growing counts, a minute per point:

The 2,000 kicked boxes cost 11% of one core and stay at the limit of max_updates. Boxes at rest cost the same at 100 and at 2,000.

The server runs a tick every 5 ms. One tick in a thousand took 7 ms or more in nearly every run, and the longest gaps come and go with no trend as objects grow.

Memory follows the map, not the objects: 2,000 boxes add about 11 MB to a server of 180 MB.

The numbers change by about a fifth from one session to another on the same computer, so compare runs made one after the other. The Performance page of the wiki has the time of each query.

Installation

  1. Download the latest release from Releases.
  2. Extract it into the folder of the server. It holds components/3DAndreas.dll, qawno/include/3DAndreas.inc, scriptfiles/3dandreas/world.db and scriptfiles/3dandreas/models.json.
  3. Add #include <3DAndreas> to the scripts that use it, after streamer.inc when the script shows physics objects with streamer objects.

Tested with open.mp 1.6.7 on Windows. Only a Windows build is available for now.

Usage

#include <open.mp>
#include <3DAndreas>

public OnPlayerCommandText(playerid, cmdtext[]) {
    if (strcmp(cmdtext, "/ball", true) == 0) {
        new
            Float:x,
            Float:y,
            Float:z,
            Physic:ball
        ;

        GetPlayerPos(playerid, x, y, z);
        ball = A3D_CreateSphere(1598, 0.3, x, y + 1.0, z + 1.0, 0.5, GetPlayerVirtualWorld(playerid));
        A3D_SetBounce(ball, 0.8);
        A3D_SetVelocity(ball, 0.0, 8.0, 4.0);

        return 1;
    }

    return 0;
}

public A3D_OnStopped(Physic:physicid, Float:x, Float:y, Float:z) {
    A3D_DestroyObject(physicid);

    return 1;
}

Every native, callback and setting is described in the wiki. examples/playground.pwn is a filterscript with a command for each kind of feature.

Configuration

Every setting is optional. These are the defaults:

"3dandreas": {
    "database": "scriptfiles/3dandreas/world.db",
    "models": "scriptfiles/3dandreas/models.json",
    "threads": 2,
    "rate": 60.0,
    "sync_error": 0.1,
    "sync_horizon": 0.3,
    "collision_speed": 1.0,
    "bounce_speed": 0.1,
    "contact_distance": 0.02,
    "draw_distance": 0.0,
    "max_updates": 1000,
    "floor": -100.0,
    "vehicles": true
}
KeyDescription
databaseMap database, relative to the server. When the default file is missing, scriptfiles/colandreas/ColAndreas.cadb is read instead.
modelsModel settings, relative to the server. A missing file leaves every model with the collision of the game.
threadsWorker threads of the simulation. 0 runs it on the thread of the server.
rateSimulation steps per second, at least 10.
sync_errorDistance in metres the object players see may stray from its body, or its far end may turn away, before a new move is sent.
sync_horizonSeconds ahead each move sent to the players aims.
collision_speedSlowest impact in metres per second that calls A3D_OnCollided.
bounce_speedSlowest impact in metres per second that bounces.
contact_distanceDistance in metres at which two bodies start to keep a contact.
draw_distanceDraw distance of the objects the component creates. 0.0 takes the default of the game.
max_updatesMost updates of the objects players see sent in a second. Every player acknowledges each one, and open.mp allows 3000 acknowledgements a second by default.
floorHeight under which a falling object is stopped.
vehiclesWhether vehicles take part in the physics world and in the queries.

The Configuration page of the wiki tells when to change each one.

Model settings

models.json describes models as A3D_CreateObject makes them: a shape where the game has none or a poor one, and the mass, friction, bounce, damping, rolling friction, buoyancy and sync error of each. The keys are model ids:

"1946": {
    "name": "baskt_ball_hi",
    "shape": "sphere",
    "radius": 0.208,
    "mass": 0.62,
    "bounce": 0.8,
    "rolling_friction": 0.15,
    "sync_error": 0.03
}

A model the file leaves out keeps the collision of the game. Its mass is its volume times the density of what its collision is made of, so the wooden crate 1224 comes out at 42 kilograms, and its friction and bounce come from the same material. A mass passed to A3D_CreateObject wins over both. The file is read once when the server starts, in about a millisecond, and a longer file does not make objects slower to create. The Model settings page of the wiki lists every setting and the materials.

Map database

world.db holds the collision of every model of the game with the surface of each part, the map objects with their interiors, the water, the surfaces of surfinfo.dat and the object.dat data of the objects that can be knocked over. The release ships one built from GTA San Andreas and the models SA-MP adds. phydb, built with the component, makes it again from a game folder, and the file goes to scriptfiles/3dandreas:

phydb "C:\Games\GTA San Andreas" world.db

--no-samp after the output leaves out the models of the SA-MP client. A ColAndreas database still loads as a fallback, without surfaces, water and model data.

Building

Windows with Visual Studio 2022 or its Build Tools, and CMake 3.19 or later. CMake fetches the open.mp SDK, the Pawn headers and Jolt Physics.

cmake -S . -B build -A Win32
cmake --build build --config Release

The component is written to build/Release/3DAndreas.dll and the database builder to build/Release/phydb.exe. The server is 32 bit, so the component must be too.

Tests

The scripts in tests run as the main script, print what they check and shut the server down. They work on the Los Santos airport, and the ones that use bots need the NPC component of open.mp with max_bots set to three or more.

ScriptWhat it checks
smoke.pwnA sphere, a box and a model shaped object dropped on the ground.
features.pwnZones, rolling friction, planar motion, gravity, acceleration, collision flags, cylinders and areas.
streamer.pwnA box shown by a streamer object. Needs the streamer plugin.
queries.pwnRays, ground, sight, sweeps, overlaps, worlds, bots and vehicles in shapes, and the cost of each native.
vehicles.pwnVehicles in the physics world, explosions and the target of a player.
parked.pwnThe time a thousand parked vehicles cost.
database.pwnThe surface of hits, water and floating objects, model data and the names and flags of surfaces.
buildings.pwnBuilding removal for every world and for one, model overlaps, extra data, rotations and reflections.
probes.pwnActors, sight in searches, points inside the map, free spots, throws, offsets, vehicle parts and the screen.
stress.pwnFour load scenarios, picked with PHYBENCH_SCENARIO=1 to 4 and sized with PHYBENCH_COUNT on the pawncc command line.
colandreas.pwnThe comparison above. Compiled with BENCH_COLANDREAS defined, it runs the same queries on ColAndreas.

Thanks to

License

Released under the MIT License. Jolt Physics keeps its own MIT license, which the release ships as LICENSE-Jolt.txt.

collisiongta-sajolt-physicsopen-mpopen-mp-componentpawnphysicssa-mpsamp

This page is built from what GitHub publishes about the repository. samp.directory does not host the code. Report a problem with this listing

imshooter/3DAndreas: SA-MP Plugin | samp.directory