top of page
Search
  • cedarcantab

s2 sample


// SPDX-FileCopyrightText: 2024 Erin Catto
// SPDX-License-Identifier: MIT

#pragma once

#include "solver2d/id.h"
#include "solver2d/manifold.h"
#include "solver2d/timer.h"
#include "solver2d/types.h"

#include "draw.h"

#include <stdlib.h>

struct Settings;
class Test;

#ifdef _DEBUG
constexpr bool g_sampleDebug = true;
#else
constexpr bool g_sampleDebug = false;
#endif

#define RAND_LIMIT 32767

/// Random number in range [-1,1]
inline float RandomFloat()
{
	float r = (float)(rand() & (RAND_LIMIT));
	r /= RAND_LIMIT;
	r = 2.0f * r - 1.0f;
	return r;
}

/// Random floating point number in range [lo, hi]
inline float RandomFloat(float lo, float hi)
{
	float r = (float)(rand() & (RAND_LIMIT));
	r /= RAND_LIMIT;
	r = (hi - lo) * r + lo;
	return r;
}

class Sample
{
  public:
	Sample(const Settings& settings, s2SolverType solverType);
	virtual ~Sample();

	void DrawTitle(Settings& settings, const char* string);
	virtual void Step(Settings& settings, s2Color bodyColor);
	virtual void UpdateUI()
	{
	}
	virtual void Keyboard(int)
	{
	}
	virtual void KeyboardUp(int)
	{
	}
	virtual void MouseDown(s2Vec2 p, int button, int mod);
	virtual void MouseUp(s2Vec2 p, int button);
	virtual void MouseMove(s2Vec2 p);

	s2SolverType m_solverType;
	s2BodyId m_groundBodyId;
	s2WorldId m_worldId;
	s2JointId m_mouseJointId;
	int m_stepCount;
	int m_textIncrement;
};

typedef Sample* SampleCreateFcn(const Settings& settings, s2SolverType solverType);

int RegisterSample(const char* category, const char* name, SampleCreateFcn* fcn);

struct SampleEntry
{
	const char* category;
	const char* name;
	SampleCreateFcn* createFcn;
};

#define MAX_SAMPLES 256
extern SampleEntry g_sampleEntries[MAX_SAMPLES];
extern int g_sampleCount;

cpp


// SPDX-FileCopyrightText: 2024 Erin Catto
// SPDX-License-Identifier: MIT

#include "sample.h"

#include "settings.h"
#include "solver2d/callbacks.h"
#include "solver2d/manifold.h"
#include "solver2d/math.h"
#include "solver2d/solver2d.h"
#include "solver2d/timer.h"

#include <GLFW/glfw3.h>
#include <stdio.h>
#include <string.h>

Sample::Sample(const Settings& settings, s2SolverType solverType)
{
	s2Vec2 gravity = {0.0f, -10.0f};

	s2WorldDef worldDef = s2DefaultWorldDef();
	worldDef.solverType = solverType;

	m_solverType = solverType;
	m_worldId = s2CreateWorld(&worldDef);
	m_mouseJointId = s2_nullJointId;

	m_stepCount = 0;
}

Sample::~Sample()
{
	s2DestroyWorld(m_worldId);
}

void Sample::DrawTitle(Settings& settings, const char* string)
{
	g_draw.DrawString(5, 5, string);
	settings.textLine = int32_t(26.0f);
}

struct QueryContext
{
	s2Vec2 point;
	s2BodyId bodyId = s2_nullBodyId;
};

bool QueryCallback(s2ShapeId shapeId, void* context)
{
	QueryContext* queryContext = static_cast<QueryContext*>(context);

	s2BodyId bodyId = s2Shape_GetBody(shapeId);
	s2BodyType bodyType = s2Body_GetType(bodyId);
	if (bodyType != s2_dynamicBody)
	{
		// continue query
		return true;
	}

	bool overlap = s2Shape_TestPoint(shapeId, queryContext->point);
	if (overlap)
	{
		// found shape
		queryContext->bodyId = bodyId;
		return false;
	}

	return true;
}

void Sample::MouseDown(s2Vec2 p, int button, int mod)
{
	if (S2_NON_NULL(m_mouseJointId))
	{
		return;
	}

	if (button == GLFW_MOUSE_BUTTON_1)
	{
		// Make a small box.
		s2Box box;
		s2Vec2 d = {0.001f, 0.001f};
		box.lowerBound = s2Sub(p, d);
		box.upperBound = s2Add(p, d);

		// Query the world for overlapping shapes.
		QueryContext queryContext = {p, s2_nullBodyId};
		s2World_QueryAABB(m_worldId, box, QueryCallback, &queryContext);

		if (S2_NON_NULL(queryContext.bodyId))
		{
			s2BodyDef bodyDef = s2_defaultBodyDef;
			m_groundBodyId = s2CreateBody(m_worldId, &bodyDef);

			s2MouseJointDef jd;
			jd.bodyIdA = m_groundBodyId;
			jd.bodyIdB = queryContext.bodyId;
			jd.target = p;
			jd.hertz = 4.0f;
			jd.dampingRatio = 1.0f;

			m_mouseJointId = s2CreateMouseJoint(m_worldId, &jd);
		}
	}
}

void Sample::MouseUp(s2Vec2 p, int button)
{
	if (S2_NON_NULL(m_mouseJointId) && button == GLFW_MOUSE_BUTTON_1)
	{
		s2DestroyJoint(m_mouseJointId);
		m_mouseJointId = s2_nullJointId;

		s2DestroyBody(m_groundBodyId);
		m_groundBodyId = s2_nullBodyId;
	}
}

void Sample::MouseMove(s2Vec2 p)
{
	if (S2_NON_NULL(m_mouseJointId))
	{
		s2MouseJoint_SetTarget(m_mouseJointId, p);
	}
}

void Sample::Step(Settings& settings, s2Color bodyColor)
{
	bodyColor.a = 0.6f;
	g_draw.m_debugDraw.dynamicBodyColor = bodyColor;

	if (settings.timeStep > 0.0f)
	{
		for (int i = 0; i < settings.multiSteps; ++i)
		{
			s2World_Step(m_worldId, settings.timeStep, settings.primaryIterations, settings.secondaryIterations, settings.enableWarmStarting);
			++m_stepCount;
		}
	}

	if (settings.enabledSolvers[m_solverType])
	{
		s2World_Draw(m_worldId, &g_draw.m_debugDraw);
	}

	if (settings.drawStats)
	{
		s2Statistics s = s2World_GetStatistics(m_worldId);

		g_draw.DrawString(5, settings.textLine, "bodies/contacts/joints = %d/%d/%d", s.bodyCount, s.contactCount, s.jointCount);
		settings.textLine += settings.textIncrement;

		g_draw.DrawString(5, settings.textLine, "proxies/height = %d/%d", s.proxyCount, s.treeHeight);
		settings.textLine += settings.textIncrement;

		g_draw.DrawString(5, settings.textLine, "stack allocator capacity/used = %d/%d", s.stackCapacity, s.stackUsed);
		settings.textLine += settings.textIncrement;
	}
}

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

int RegisterSample(const char* category, const char* name, SampleCreateFcn* fcn)
{
	int index = g_sampleCount;
	if (index < MAX_SAMPLES)
	{
		g_sampleEntries[index] = {category, name, fcn};
		++g_sampleCount;
		return index;
	}

	return -1;
}

3 views0 comments

Recent Posts

See All

b2Distance

// MIT License // Copyright (c) 2019 Erin Catto // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"

p2 naive broadphase

var Broadphase = require('../collision/Broadphase'); module.exports = NaiveBroadphase; /** * Naive broadphase implementation. Does N^2 tests. * * @class NaiveBroadphase * @constructor * @extend

Extending Box2D-Lite in Javascript: Revolute Joint

/// Revolute joint definition. This requires defining an anchor point where the /// bodies are joined. The definition uses local anchor points so that the /// initial configuration can violate the con

記事: Blog2_Post
bottom of page