Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- package main
- import rl "vendor:raylib"
- import rlgl "vendor:raylib/rlgl"
- Point :: struct {
- pos: rl.Vector2,
- prevPos: rl.Vector2,
- initPos: rl.Vector2,
- isPinned: bool,
- isSelected: bool,
- }
- Stick :: struct {
- p0: int, // index
- p1: int,
- isTeared: bool
- }
- Cloth :: struct {
- points: #soa[dynamic]Point,
- sticks: #soa[dynamic]Stick,
- }
- main :: proc() {
- rl.InitWindow(800, 500, cstring("Some libreary"))
- screenWidth := rl.GetScreenWidth()
- screenHeight := rl.GetScreenHeight()
- //rl.SetTargetFPS(60)
- clothWidth :: 50
- clothHeight :: 50
- clothSpacing :: 10
- startX := (screenWidth - (clothWidth * clothSpacing)) / 2
- startY := screenHeight/12
- cloth := MakeCloth(clothWidth, clothHeight, clothSpacing, startX, startY)
- defer delete(cloth.points)
- defer delete(cloth.sticks)
- particleShader := rl.LoadShader("shader.vert", "shader.frag")
- ssbo0 := rlgl.LoadShaderBuffer(u32(len(cloth.points)) * size_of(Point), &cloth.points, rlgl.DYNAMIC_COPY)
- particleVao := rlgl.LoadVertexArray()
- rlgl.EnableVertexArray(particleVao)
- rlgl.EnableVertexArray(0)
- drag :: f32(0.005)
- gravity :: rl.Vector2{0, 980}
- elasticity :: f32(100.0)
- fixedDeltaTime :: f32(1.0 / 300)
- accumulator: f32 = 0.0
- cursorSize: f32 = 30.0
- for !rl.WindowShouldClose() {
- HandleMouseInteraction(&cloth, &cursorSize)
- accumulator += rl.GetFrameTime()
- for accumulator >= fixedDeltaTime {
- UpdateCloth(&cloth, fixedDeltaTime, clothSpacing, drag, gravity, elasticity)
- accumulator -= fixedDeltaTime
- }
- rl.BeginDrawing()
- rl.ClearBackground({33, 40, 48, 255})
- //rl.ClearBackground(rl.ORANGE)
- DrawCloth(&cloth, clothSpacing, elasticity)
- rl.DrawFPS(50 , 50)
- rl.EndDrawing()
- }
- rl.CloseWindow();
- }
- MakeCloth :: proc(width, height, spacing, startX, startY: i32) -> Cloth {
- cloth: Cloth
- cloth.points = make(#soa[dynamic]Point, 0)
- cloth.sticks = make(#soa[dynamic]Stick, 0)
- for y := i32(0); y <= height; y += 1 {
- for x := i32(0); x <= width; x += 1 {
- point: Point
- point.initPos = { f32(startX + x * spacing), f32(startY + y * spacing) }
- point.pos = point.initPos
- point.prevPos = point.initPos
- point.isPinned = y == 0
- append(&cloth.points, point)
- if x != 0 {
- stick: Stick
- stick.p0 = len(cloth.points) - 2
- stick.p1 = len(cloth.points) - 1
- append(&cloth.sticks, stick)
- }
- if y != 0 {
- stick: Stick
- stick.p0 = int((y - 1) * (width + 1) + x)
- stick.p1 = int( y * (width + 1) + x)
- append(&cloth.sticks, stick)
- }
- }
- }
- return cloth
- }
- UpdateCloth :: proc(cloth: ^Cloth, deltatime: f32, spacing: i32, drag: f32, accerlation: rl.Vector2, elasticity: f32) {
- for &point in cloth.points {
- if point.isPinned {
- point.pos = point.initPos
- continue
- }
- currentPos := point.pos
- point.pos += (point.pos - point.prevPos) * (1.0 - drag) + accerlation * deltatime * deltatime
- point.prevPos = currentPos
- }
- for &stick in cloth.sticks {
- p0 := &cloth.points[ stick.p0]
- p1 := &cloth.points[ stick.p1]
- delta := p1.pos - p0.pos
- distance := rl.Vector2Length(delta)
- if distance > elasticity {
- stick.isTeared = true
- continue
- }
- correction: rl.Vector2 = delta * ((distance - f32(spacing)) / distance * 0.5) * 0.5
- if !p0.isPinned && !stick.isTeared {
- p0.pos += correction
- }
- if !p1.isPinned && !stick.isTeared {
- p1.pos -= correction
- }
- }
- }
- DrawCloth :: proc(cloth: ^Cloth, spacing: int, elasticity: f32) {
- for stick in cloth.sticks {
- DrawStick( cloth, stick, spacing, elasticity)
- }
- DrawStick :: proc(cloth: ^Cloth, stick: Stick, spacing: int, elasticity: f32) {
- if (stick.isTeared) {
- return
- }
- p0 := cloth.points[stick.p0]
- p1 := cloth.points[stick.p1]
- distance := rl.Vector2Distance(p0.pos, p1.pos)
- color := p0.isSelected || p1.isSelected ? rl.BLUE : GetColorFromTension(distance, elasticity, spacing)
- rl.DrawLineV( p0.pos, p1.pos, color)
- }
- }
- GetColorFromTension :: proc(distance: f32, elasticity: f32, spacing: int) -> rl.Color {
- if distance <= f32(spacing) {
- return {
- 44,
- 222,
- 130,
- 255
- } // Green
- } else if distance <= f32(spacing) * 1.33 {
- t := (distance - f32(spacing)) / (f32(spacing) * 0.33)
- return {
- Lerp(44, 255, t),
- Lerp(222, 255, t),
- Lerp(130, 0, t),
- 255
- } // Gradual transition to yellow
- } else {
- t := (distance - f32(spacing) * 1.33) / (elasticity - f32(spacing) * 1.33)
- return {
- Lerp(255, 222, t),
- Lerp(255, 44, t),
- Lerp(0, 44, t),
- 255
- } // Gradual transition to red
- }
- Lerp :: proc(a: f32, b: f32, t: f32) -> u8 {
- return u8(a + ((b - a) * t))
- }
- }
- HandleMouseInteraction :: proc(cloth: ^Cloth, cursorSize: ^f32) {
- stepSize :: 5
- if rl.GetMouseWheelMove() > 0 {
- cursorSize^ += stepSize
- } else if rl.GetMouseWheelMove() < 0 && cursorSize^ > stepSize {
- cursorSize^ -= stepSize
- }
- @(static)prevMousePos: rl.Vector2
- mousePos := rl.GetMousePosition()
- maxDelta := rl.Vector2(100)
- mouseDelta := rl.Vector2Clamp(mousePos - prevMousePos, rl.Vector2(0), maxDelta)
- for &point in cloth.points {
- distance := rl.Vector2Distance(mousePos, point.pos)
- if distance < cursorSize^ {
- if rl.IsMouseButtonDown(.LEFT) {
- point.prevPos = point.prevPos + mouseDelta
- point.pos = point.pos + mouseDelta
- }
- point.isSelected = true
- } else {
- point.isSelected = false
- }
- }
- prevMousePos = mousePos
- }
Advertisement
Add Comment
Please, Sign In to add comment