Created
December 16, 2018 22:18
-
-
Save JSandusky/37c12758fdf4dcbfbc3faa67e6ab5762 to your computer and use it in GitHub Desktop.
Repro for Physics 2d raycast bug
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Urho2D physics sample. | |
// This sample demonstrates: | |
// - Creating both static and moving 2D physics objects to a scene | |
// - Displaying physics debug geometry | |
#include "Scripts/Utilities/Sample.as" | |
void Start() | |
{ | |
// Execute the common startup for samples | |
SampleStart(); | |
// Create the scene content | |
CreateScene(); | |
// Create the UI content | |
CreateInstructions(); | |
// Setup the viewport for displaying the scene | |
SetupViewport(); | |
// Set the mouse mode to use in the sample | |
SampleInitMouseMode(MM_FREE); | |
// Hook up to the frame update events | |
SubscribeToEvents(); | |
} | |
void CreateScene() | |
{ | |
scene_ = Scene(); | |
// Create the Octree component to the scene. This is required before adding any drawable components, or else nothing will | |
// show up. The default octree volume will be from (-1000, -1000, -1000) to (1000, 1000, 1000) in world coordinates; it | |
// is also legal to place objects outside the volume but their visibility can then not be checked in a hierarchically | |
// optimizing manner | |
scene_.CreateComponent("Octree"); | |
scene_.CreateComponent("DebugRenderer"); | |
// Create a scene node for the camera, which we will move around | |
// The camera will use default settings (1000 far clip distance, 45 degrees FOV, set aspect ratio automatically) | |
cameraNode = scene_.CreateChild("Camera"); | |
// Set an initial position for the camera scene node above the plane | |
cameraNode.position = Vector3(0.0f, 0.0f, -10.0f); | |
Camera@ camera = cameraNode.CreateComponent("Camera"); | |
camera.orthographic = true; | |
camera.orthoSize = graphics.height * PIXEL_SIZE; | |
camera.zoom = 1.2f * Min(graphics.width / 1280.0f, graphics.height / 800.0f); // Set zoom according to user's resolution to ensure full visibility (initial zoom (1.2) is set for full visibility at 1280x800 resolution) | |
// Create 2D physics world component | |
scene_.CreateComponent("PhysicsWorld2D"); | |
Sprite2D@ boxSprite = cache.GetResource("Sprite2D", "Urho2D/Box.png"); | |
Sprite2D@ ballSprite = cache.GetResource("Sprite2D", "Urho2D/Ball.png"); | |
// Create ground. | |
Node@ groundNode = scene_.CreateChild("Ground"); | |
groundNode.position = Vector3(0.0f, -3.0f, 0.0f); | |
groundNode.scale = Vector3(200.0f, 1.0f, 0.0f); | |
// Create 2D rigid body for gound | |
RigidBody2D@ groundBody = groundNode.CreateComponent("RigidBody2D"); | |
StaticSprite2D@ groundSprite = groundNode.CreateComponent("StaticSprite2D"); | |
groundSprite.sprite = boxSprite; | |
// Create box collider for ground | |
CollisionBox2D@ groundShape = groundNode.CreateComponent("CollisionBox2D"); | |
// Set box size | |
groundShape.size = Vector2(0.32f, 0.32f); | |
// Set friction | |
groundShape.friction = 0.5f; | |
groundShape.categoryBits = 4; | |
const uint NUM_OBJECTS = 100; | |
for (uint i = 0; i < NUM_OBJECTS; ++i) | |
{ | |
Node@ node = scene_.CreateChild("RigidBody"); | |
node.position = Vector3(Random(-0.1f, 0.1f), 5.0f + i * 0.4f, 0.0f); | |
// Create rigid body | |
RigidBody2D@ body = node.CreateComponent("RigidBody2D"); | |
body.bodyType = BT_DYNAMIC; | |
StaticSprite2D@ staticSprite = node.CreateComponent("StaticSprite2D"); | |
if (i % 2 == 0) | |
{ | |
staticSprite.sprite = boxSprite; | |
// Create box | |
CollisionBox2D@ box = node.CreateComponent("CollisionBox2D"); | |
// Set size | |
box.size = Vector2(0.32f, 0.32f); | |
// Set density | |
box.density = 1.0f; | |
// Set friction | |
box.friction = 0.5f; | |
// Set restitution | |
box.restitution = 0.1f; | |
box.categoryBits = 1; | |
box.maskBits = 1 + 4; | |
} | |
else | |
{ | |
staticSprite.sprite = ballSprite; | |
// Create circle | |
CollisionCircle2D@ circle = node.CreateComponent("CollisionCircle2D"); | |
// Set radius | |
circle.radius = 0.16f; | |
// Set density | |
circle.density = 1.0f; | |
// Set friction. | |
circle.friction = 0.5f; | |
// Set restitution | |
circle.restitution = 0.1f; | |
circle.categoryBits = 2; | |
circle.maskBits = 2 + 4; | |
} | |
} | |
} | |
void CreateInstructions() | |
{ | |
// Construct new Text object, set string to display and font to use | |
Text@ instructionText = ui.root.CreateChild("Text"); | |
instructionText.text = "Use WASD keys and mouse to move, Use PageUp PageDown to zoom."; | |
instructionText.SetFont(cache.GetResource("Font", "Fonts/Anonymous Pro.ttf"), 15); | |
// Position the text relative to the screen center | |
instructionText.horizontalAlignment = HA_CENTER; | |
instructionText.verticalAlignment = VA_CENTER; | |
instructionText.SetPosition(0, ui.root.height / 4); | |
} | |
void SetupViewport() | |
{ | |
// Set up a viewport to the Renderer subsystem so that the 3D scene can be seen. We need to define the scene and the camera | |
// at minimum. Additionally we could configure the viewport screen size and the rendering path (eg. forward / deferred) to | |
// use, but now we just use full screen and default render path configured in the engine command line options | |
Viewport@ viewport = Viewport(scene_, cameraNode.GetComponent("Camera")); | |
renderer.viewports[0] = viewport; | |
} | |
void MoveCamera(float timeStep) | |
{ | |
// Do not move if the UI has a focused element (the console) | |
if (ui.focusElement !is null) | |
return; | |
// Movement speed as world units per second | |
const float MOVE_SPEED = 4.0f; | |
// Read WASD keys and move the camera scene node to the corresponding direction if they are pressed | |
if (input.keyDown[KEY_W]) | |
cameraNode.Translate(Vector3::UP * MOVE_SPEED * timeStep); | |
if (input.keyDown[KEY_S]) | |
cameraNode.Translate(Vector3::DOWN * MOVE_SPEED * timeStep); | |
if (input.keyDown[KEY_A]) | |
cameraNode.Translate(Vector3::LEFT * MOVE_SPEED * timeStep); | |
if (input.keyDown[KEY_D]) | |
cameraNode.Translate(Vector3::RIGHT * MOVE_SPEED * timeStep); | |
if (input.keyDown[KEY_PAGEUP]) | |
{ | |
Camera@ camera = cameraNode.GetComponent("Camera"); | |
camera.zoom = camera.zoom * 1.01f; | |
} | |
if (input.keyDown[KEY_PAGEDOWN]) | |
{ | |
Camera@ camera = cameraNode.GetComponent("Camera"); | |
camera.zoom = camera.zoom * 0.99f; | |
} | |
} | |
void SubscribeToEvents() | |
{ | |
// Subscribe HandleUpdate() function for processing update events | |
SubscribeToEvent("Update", "HandleUpdate"); | |
SubscribeToEvent("MouseButtonDown", "HandleMouseDown"); | |
SubscribeToEvent("MouseButtonUp", "HandleMouseUp"); | |
// Unsubscribe the SceneUpdate event from base class to prevent camera pitch and yaw in 2D sample | |
UnsubscribeFromEvent("SceneUpdate"); | |
} | |
IntVector2 mouseStartPos; | |
IntVector2 end; | |
Vector3 rayBase = Vector3(0,0,0); | |
Vector3 rayEnd = Vector3(0,0,0); | |
Vector3 rayLocation = Vector3(0,0,0); | |
void HandleMouseDown(StringHash eventType, VariantMap& eventData) | |
{ | |
if (eventData["Button"].GetInt() == 1) | |
{ | |
mouseStartPos = input.mousePosition; | |
Camera@ cam = scene_.GetChild("Camera").GetComponent("Camera"); | |
rayBase = GetMouseWorld(); | |
log.Error("Starting ray"); | |
} | |
} | |
void HandleMouseUp(StringHash eventType, VariantMap& eventData) | |
{ | |
if (eventData["Button"].GetInt() == 1) | |
{ | |
log.Error("Casting ray!"); | |
PhysicsWorld2D@ world = scene_.GetComponent("PhysicsWorld2D"); | |
IntVector2 newMouse = input.mousePosition; | |
rayEnd = GetMouseWorld(); | |
PhysicsRaycastResult2D results = world.RaycastSingle(Vector2(rayBase.x, rayBase.y), Vector2(rayEnd.x, rayEnd.y), 2); | |
if (results.body !is null) | |
{ | |
log.Error("Hit a body!"); | |
rayLocation = Vector3(results.position.x, results.position.y, 0); | |
} | |
} | |
} | |
Vector3 GetMouseWorld() | |
{ | |
Camera@ cam = scene_.GetChild("Camera").GetComponent("Camera"); | |
Vector3 v = Vector3(input.mousePosition.x, input.mousePosition.y, 0); | |
v = v / Vector3(graphics.width, graphics.height, 1); | |
return cam.ScreenToWorldPoint(v); | |
} | |
void DrawRayInfo() | |
{ | |
DebugRenderer@ render = scene_.GetOrCreateComponent("DebugRenderer"); | |
render.AddCross(rayLocation, 2, RED); | |
render.AddLine(rayBase, rayEnd, GREEN); | |
} | |
void HandleUpdate(StringHash eventType, VariantMap& eventData) | |
{ | |
// Take the frame time step, which is stored as a float | |
float timeStep = eventData["TimeStep"].GetFloat(); | |
// Move the camera, scale movement with time step | |
MoveCamera(timeStep); | |
if (input.mouseButtonDown[0]) | |
{ | |
Camera@ cam = scene_.GetChild("Camera").GetComponent("Camera"); | |
rayEnd = cam.ScreenToWorldPoint(Vector3(input.mousePosition.x / graphics.width, input.mousePosition.y / graphics.height, 0.5)); | |
} | |
DrawRayInfo(); | |
} | |
// Create XML patch instructions for screen joystick layout specific to this sample app | |
String patchInstructions = | |
"<patch>" + | |
" <remove sel=\"/element/element[./attribute[@name='Name' and @value='Button0']]/attribute[@name='Is Visible']\" />" + | |
" <replace sel=\"/element/element[./attribute[@name='Name' and @value='Button0']]/element[./attribute[@name='Name' and @value='Label']]/attribute[@name='Text']/@value\">Zoom In</replace>" + | |
" <add sel=\"/element/element[./attribute[@name='Name' and @value='Button0']]\">" + | |
" <element type=\"Text\">" + | |
" <attribute name=\"Name\" value=\"KeyBinding\" />" + | |
" <attribute name=\"Text\" value=\"PAGEUP\" />" + | |
" </element>" + | |
" </add>" + | |
" <remove sel=\"/element/element[./attribute[@name='Name' and @value='Button1']]/attribute[@name='Is Visible']\" />" + | |
" <replace sel=\"/element/element[./attribute[@name='Name' and @value='Button1']]/element[./attribute[@name='Name' and @value='Label']]/attribute[@name='Text']/@value\">Zoom Out</replace>" + | |
" <add sel=\"/element/element[./attribute[@name='Name' and @value='Button1']]\">" + | |
" <element type=\"Text\">" + | |
" <attribute name=\"Name\" value=\"KeyBinding\" />" + | |
" <attribute name=\"Text\" value=\"PAGEDOWN\" />" + | |
" </element>" + | |
" </add>" + | |
"</patch>"; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment