Skip to content

Commit

Permalink
b2SurfaceMaterial for chain shapes
Browse files Browse the repository at this point in the history
  • Loading branch information
erincatto committed Jan 27, 2025
1 parent e441b77 commit eb4c15e
Show file tree
Hide file tree
Showing 24 changed files with 523 additions and 146 deletions.
48 changes: 34 additions & 14 deletions include/box2d/types.h
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,35 @@ typedef struct b2ShapeDef
/// @ingroup shape
B2_API b2ShapeDef b2DefaultShapeDef( void );

/// Surface materials allow chain shapes to have per segment surface properties.
/// @ingroup shape
typedef struct b2SurfaceMaterial
{
/// The Coulomb (dry) friction coefficient, usually in the range [0,1].
float friction;

/// The coefficient of restitution (bounce) usually in the range [0,1].
/// https://en.wikipedia.org/wiki/Coefficient_of_restitution
float restitution;

/// The rolling resistance usually in the range [0,1].
float rollingResistance;

/// The tangent speed for conveyor belts
float tangentSpeed;

/// User material identifier. This is passed with query results and to friction and restitution
/// combining functions. It is not used internally.
int material;

/// Custom debug draw color.
uint32_t customColor;
} b2SurfaceMaterial;

/// Use this to initialize your surface material
/// @ingroup shape
B2_API b2SurfaceMaterial b2DefaultSurfaceMaterial( void );

/// Used to create a chain of line segments. This is designed to eliminate ghost collisions with some limitations.
/// - chains are one-sided
/// - chains have no mass and should be used on static bodies
Expand All @@ -422,28 +451,19 @@ typedef struct b2ChainDef
/// The point count, must be 4 or more.
int count;

/// The friction coefficient, usually in the range [0,1].
float friction;
/// Surface materials for each segment. These are cloned.
const b2SurfaceMaterial* materials;

/// The restitution (elasticity) usually in the range [0,1].
float restitution;

/// User material identifier. This is passed with query results and to friction and restitution
/// combining functions. It is not used internally.
int material;
/// The material count. Must be 1 or count. This allows you to provide one
/// material for all segments or a unique material per segment.
int materialCount;

/// Contact filtering data.
b2Filter filter;

/// Custom debug draw color.
uint32_t customColor;

/// Indicates a closed chain formed by connecting the first and last points
bool isLoop;

/// Generate events when a sensor overlaps this chain
bool enableSensorEvents;

/// Used internally to detect a valid definition. DO NOT SET.
int internalValue;
} b2ChainDef;
Expand Down
66 changes: 66 additions & 0 deletions samples/data/ramp.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
145 changes: 143 additions & 2 deletions samples/sample.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
// SPDX-FileCopyrightText: 2023 Erin Catto
// SPDX-License-Identifier: MIT

#define _CRT_SECURE_NO_WARNINGS

#include "sample.h"

#include "TaskScheduler.h"
Expand Down Expand Up @@ -118,7 +120,7 @@ Sample::Sample( Settings& settings )

m_settings = &settings;

CreateWorld( );
CreateWorld();
TestMathCpp();
}

Expand All @@ -131,7 +133,7 @@ Sample::~Sample()
delete[] m_tasks;
}

void Sample::CreateWorld( )
void Sample::CreateWorld()
{
if ( B2_IS_NON_NULL( m_worldId ) )
{
Expand Down Expand Up @@ -503,6 +505,145 @@ void Sample::ShiftOrigin( b2Vec2 newOrigin )
// m_world->ShiftOrigin(newOrigin);
}

// const char* path =
// "M 47.625004,185.20833 H 161.39585 l 29.10417,-2.64583 26.45834,-7.9375 26.45833,-13.22917 23.81251,-21.16666 h "
// "13.22916 v 44.97916 H 592.66669 V 0 h 21.16671 v 206.375 l -566.208398,-1e-5";

int Sample::ParsePath( const char* svgPath, b2Vec2 offset, b2Vec2* points, int capacity, float scale, bool reverseOrder )
{
int pointCount = 0;
b2Vec2 currentPoint = {};
const char* ptr = svgPath;
char command = *ptr;

while ( *ptr != '\0' )
{
if ( isdigit( *ptr ) == 0 && *ptr != '-' )
{
// note: command can be implicitly repeated
command = *ptr;

if ( command == 'M' || command == 'L' || command == 'H' || command == 'V' || command == 'm' || command == 'l' ||
command == 'h' || command == 'v' )
{
ptr += 2; // Skip the command character and space
}

if ( command == 'z' )
{
break;
}
}

assert( isdigit( *ptr ) != 0 || *ptr == '-' );

float x = 0.0f, y = 0.0f;
switch ( command )
{
case 'M':
case 'L':
if ( sscanf( ptr, "%f,%f", &x, &y ) == 2 )
{
currentPoint.x = x;
currentPoint.y = y;
}
else
{
assert( false );
}
break;
case 'H':
if ( sscanf( ptr, "%f", &x ) == 1 )
{
currentPoint.x = x;
}
else
{
assert( false );
}
break;
case 'V':
if ( sscanf( ptr, "%f", &y ) == 1 )
{
currentPoint.y = y;
}
else
{
assert( false );
}
break;
case 'm':
case 'l':
if ( sscanf( ptr, "%f,%f", &x, &y ) == 2 )
{
currentPoint.x += x;
currentPoint.y += y;
}
else
{
assert( false );
}
break;
case 'h':
if ( sscanf( ptr, "%f", &x ) == 1 )
{
currentPoint.x += x;
}
else
{
assert( false );
}
break;
case 'v':
if ( sscanf( ptr, "%f", &y ) == 1 )
{
currentPoint.y += y;
}
else
{
assert( false );
}
break;

default:
assert( false );
break;
}

points[pointCount] = { scale * ( currentPoint.x + offset.x ), -scale * ( currentPoint.y + offset.y ) };
pointCount += 1;
if ( pointCount == capacity )
{
break;
}

// Move to the next space or end of string
while ( *ptr != '\0' && isspace( *ptr ) == 0 )
{
ptr++;
}

// Skip contiguous spaces
while ( isspace( *ptr ) )
{
ptr++;
}

ptr += 0;
}

if ( pointCount == 0 )
{
return 0;
}

if ( reverseOrder )
{

}
return pointCount;
}

SampleEntry g_sampleEntries[MAX_SAMPLES] = {};
int g_sampleCount = 0;

Expand Down
2 changes: 2 additions & 0 deletions samples/sample.h
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,8 @@ class Sample
void ResetProfile();
void ShiftOrigin( b2Vec2 newOrigin );

static int ParsePath( const char* svgPath, b2Vec2 offset, b2Vec2* points, int capacity, float scale, bool reverseOrder );

friend class DestructionListener;
friend class BoundaryListener;
friend class ContactListener;
Expand Down
6 changes: 5 additions & 1 deletion samples/sample_continuous.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -667,11 +667,15 @@ class GhostBumps : public Sample
points[18] = b2Add( points[17], { -2.0f * hx, 0.0f } );
points[19] = b2Add( points[18], { -2.0f * hx, 0.0f } );

b2SurfaceMaterial material = {};
material.friction = m_friction;

b2ChainDef chainDef = b2DefaultChainDef();
chainDef.points = points;
chainDef.count = 20;
chainDef.isLoop = true;
chainDef.friction = m_friction;
chainDef.materials = &material;
chainDef.materialCount = 1;

b2CreateChain( m_groundId, &chainDef );
}
Expand Down
6 changes: 5 additions & 1 deletion samples/sample_events.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -92,11 +92,15 @@ class SensorFunnel : public Sample
// }
// printf("};\n");

b2SurfaceMaterial material = {};
material.friction = 0.2f;

b2ChainDef chainDef = b2DefaultChainDef();
chainDef.points = points;
chainDef.count = count;
chainDef.isLoop = true;
chainDef.friction = 0.2f;
chainDef.materials = &material;
chainDef.materialCount = 1;
b2CreateChain( groundId, &chainDef );

float sign = 1.0f;
Expand Down
Loading

0 comments on commit eb4c15e

Please sign in to comment.