This commit is contained in:
sam
2026-03-17 09:34:15 +05:45
parent 0fe796ea19
commit 493338d91b
5 changed files with 107 additions and 31 deletions
+89 -14
View File
@@ -1,7 +1,7 @@
package ion
import b2 "vendor:box2d"
import array "core:container/small_array"
import "core:fmt"
static_index :: i32
@@ -41,6 +41,7 @@ engine_entity_flags_enum :: enum u64 {
POLYGON_IS_BOX,
MULTI_BODIES,
CHAIN,
CHAIN_CUSTOM,
MULTI_SHAPES,
}
@@ -56,7 +57,8 @@ engine_entity_def :: struct {
centers : [2]b2.Vec2,
size : b2.Vec2,
is_loop : bool,
vertices : array.Small_Array(b2.MAX_POLYGON_VERTICES, b2.Vec2),
vertices : [dynamic; b2.MAX_POLYGON_VERTICES]b2.Vec2,
name_buf : [255]u8 `fmt:"-" cbor:"-"`,
entity_flags : engine_entity_flags,
@@ -65,11 +67,47 @@ engine_entity_def :: struct {
//For chain bodies
//It will replicate itself to the body count and connect themselves with rev_joints
body_count : i32,
rev_joint : b2.RevoluteJointDef,
half_link_length : f32
body_count : i32,
//If chain not custom then the dynamic list of link_length will be used to create the chain
//Handle the link_length like vertices
rev_joint : b2.RevoluteJointDef,
link_length_array : [dynamic]b2.Vec2,
}
compare_engine_entity_def :: proc(a, b : engine_entity_def) -> bool
{
ret := false
ret &= a.body_def == b.body_def
ret &= a.shape_def == b.shape_def
ret &= a.shape_type == b.shape_type
ret &= a.radius == b.radius
ret &= a.scale == b.scale
ret &= a.centers == b.centers
ret &= a.size == b.size
ret &= a.is_loop == b.is_loop
//ret &= a.vertices[:] == b.vertices[:]
ret &= a.name_buf == b.name_buf
if a.entity_flags != b.entity_flags{
fmt.println("Hello world")
}
ret &= a.entity_flags == b.entity_flags
ret &= a.index == b.index
ret &= a.body_count == b.body_count
ret &= a.rev_joint == b.rev_joint
//ret &= a.link_length[:] == b.link_length[:]
return ret
}
engine_entity :: struct {
body_id : b2.BodyId,
shape_id : b2.ShapeId,
@@ -132,17 +170,17 @@ engine_entity_single_body :: proc(def : ^engine_entity_def, world_id: b2.WorldId
capsule
)
}
case .chainSegmentShape:
case .chainSegmentShape:
{
chain_def := b2.DefaultChainDef()
verts :[dynamic]b2.Vec2
for &v in array.slice(&def.vertices){
for &v in def.vertices[:]{
v *= def.scale
}
for v in array.slice(&def.vertices){
for v in def.vertices[:]{
//If it's not a looped chain then it needs two defination
if !def.is_loop do append(&verts, v)
@@ -150,7 +188,6 @@ engine_entity_single_body :: proc(def : ^engine_entity_def, world_id: b2.WorldId
append(&verts, v)
}
slice := array.slice(&def.vertices)
chain_def.points = &verts[0]
chain_def.count = i32(len(verts))
@@ -171,10 +208,10 @@ engine_entity_single_body :: proc(def : ^engine_entity_def, world_id: b2.WorldId
}
case .segmentShape:
{
for &v in array.slice(&def.vertices){
for &v in def.vertices[:]{
v *= def.scale
}
segment : b2.Segment = {point1 = array.get(def.vertices, 0), point2 = array.get(def.vertices, 2)}
segment : b2.Segment = {point1 = def.vertices[0], point2 = def.vertices[2]}
new_entity.shape_id = b2.CreateSegmentShape(new_entity.body_id, def.shape_def, segment)
def.scale = 1
@@ -193,14 +230,14 @@ engine_entity_single_body :: proc(def : ^engine_entity_def, world_id: b2.WorldId
{
//def.size *= def.scale
for &v in array.slice(&def.vertices){
for &v in def.vertices[:]{
v *= def.scale
}
points := make([dynamic]b2.Vec2, 0)
for p, i in array.slice(&def.vertices){
if i >= int(def.vertices.len) do break
for p, i in def.vertices[:]{
if i >= int(len(def.vertices)) do break
append_elem(&points, p)
}
sort_points_ccw(points[:])
@@ -222,6 +259,44 @@ engine_entity_single_body :: proc(def : ^engine_entity_def, world_id: b2.WorldId
return new_entity
}
engine_create_chain_shape :: proc(def : ^engine_entity_def, world_id: b2.WorldId, index : i32) -> engine_entity
{
joint_def := def.rev_joint
orig_pos := def.body_def.position
position := def.body_def.position
prev_body_id : b2.BodyId
engine_entity := engine_entity_single_body(def, world_id, index)
for i in def.link_length_array[:]
{
rot := b2.ComputeRotationBetweenUnitVectors(def.body_def.position, position)
def.body_def.rotation = rot
def.body_def.position = position
engine_entity = engine_entity_single_body(def, world_id, index)
pivot := position - i
if i != 0
{
joint_def.bodyIdA = prev_body_id
joint_def.bodyIdB = engine_entity.body_id
joint_def.localAnchorA = b2.Body_GetLocalPoint(joint_def.bodyIdA, pivot)
joint_def.localAnchorB = b2.Body_GetLocalPoint(joint_def.bodyIdB, pivot)
joint_id := b2.CreateRevoluteJoint(world_id, joint_def)
}
position += 2 * i
prev_body_id = engine_entity.body_id
}
def.body_def.position = orig_pos
return engine_entity
}
+4 -1
View File
@@ -1,6 +1,5 @@
package ion
import "core:slice"
import "core:container/small_array"
import "core:fmt"
import im "shared:odin-imgui"
import b2 "vendor:box2d"
@@ -20,6 +19,7 @@ EditMode :: enum
ENTITY,
VERTICES,
OVERVIEW,
CHAIN,
JOINT,
}
@@ -32,6 +32,8 @@ interface_state :: struct
state : ^engine_state,
vertex_index : ^i32,
chain_index : ^i32,
edit_mode : EditMode,
curr_joint_index : i32,
@@ -43,6 +45,7 @@ interface_state :: struct
interface_draw_options :: proc(state: ^engine_state) {
debug_draw := &state.draw.debug_draw
im.SliderFloat("Zoom", &state.draw.cam.zoom, 0, 100)
im.Checkbox("Shapes", &debug_draw.drawShapes)
im.Checkbox("Joints", &debug_draw.drawJoints)
im.Checkbox("Joint Extras", &debug_draw.drawJointExtras)
+12 -15
View File
@@ -3,7 +3,6 @@ package ion
import b2 "vendor:box2d"
import im "shared:odin-imgui"
import "core:slice"
import "core:container/small_array"
import "core:fmt"
@@ -174,8 +173,8 @@ interface_shape_def_editor :: proc(def: ^engine_entity_def) -> bool
im.SliderFloat("Density", &def.shape_def.density, 0, 100)
if im.Button("Flip horizontally") do flip_points(small_array.slice(&def.vertices), .Horizontal)
if im.Button("Flip Vertically ") do flip_points(small_array.slice(&def.vertices), .Vertical)
if im.Button("Flip horizontally") do flip_points(def.vertices[:], .Horizontal)
if im.Button("Flip Vertically ") do flip_points(def.vertices[:], .Vertical)
if im.TreeNode("Events and contacts") {
im.Checkbox("Is sensor", &def.shape_def.isSensor)
@@ -217,7 +216,7 @@ interface_shape_def_editor :: proc(def: ^engine_entity_def) -> bool
interface_entity :: proc(interface: ^interface_state) -> bool
{
entity_selected := interface.selected_entity^ != -1
entity_selected := (interface.selected_entity^ != -1) && len(interface.entity_defs) > 0
if entity_selected
{
@@ -226,7 +225,7 @@ interface_entity :: proc(interface: ^interface_state) -> bool
ret := false
interface.edit_mode = .ENTITY
//interface.edit_mode = .ENTITY
//Flags
for flag in engine_entity_flags_enum
{
@@ -234,14 +233,6 @@ interface_entity :: proc(interface: ^interface_state) -> bool
if im.Checkbox(fmt.ctprint(flag), &contains) do def.entity_flags ~= {flag}
}
if .CHAIN in def.entity_flags
{
im.InputInt("Body Count", &def.body_count, 1)
im.SliderFloat("Half Link Length", &def.half_link_length, 1, 10)
}
im.Separator()
if im.CollapsingHeader("Shape Edit")
@@ -263,10 +254,16 @@ interface_entity :: proc(interface: ^interface_state) -> bool
if .CHAIN in def.entity_flags
{
interface_edit_rev_joint_minimal(&def.rev_joint)
im.InputInt("Body Count", &def.body_count)
//im.SliderFloat2("Half Link Length", &def.link_length, -10, 10)
if im.CollapsingHeader("Chain joint def")
{
interface_edit_rev_joint_minimal(&def.rev_joint)
}
}
return def^ != def_old || ret
return !compare_engine_entity_def(def^, def_old) || ret
}
return false
+1 -1
View File
@@ -267,7 +267,7 @@ interface_edit_revolute_joint :: proc( interface : ^interface_state ) -> bool
interface_joints :: proc(interface: ^interface_state) -> bool
{
ret := false
interface.edit_mode = .JOINT
//interface.edit_mode = .JOINT
if im.BeginCombo("Joint type", fmt.ctprint(interface.curr_joint_type))
{
+1
View File
@@ -102,6 +102,7 @@ engine_init :: proc(state: ^engine_state)
return nil
},
}, 201, rawptr)
}
update_frame :: proc(state: ^engine_state)