3D Engine Overlay
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © peacefulLizard50262
//USE 1W TIME FRAME OR GREATER
//@version=5
indicator("3D Engine", max_bars_back = 5000, max_lines_count = 500, overlay = true)


scale_factor = open

type vector2
    float x
    float y

type vector3
    float x
    float y
    float z

type vector4
    float x
    float y
    float z
    float w

type face
    int v1
    int v2
    int v3

type mesh
    array<vector4> v
    array<face> f

type mesh2d
    array<vector2> v
    array<face> f

type location
    vector3 position
    vector3 theta
    vector3 scale

type object
    mesh m
    location l

type poly4
    float x1
    float x2
    float y1
    float y2

type polyg
    poly4 l1 
    poly4 l2
    poly4 l3

type camera
    vector3 pos //position
    vector3 tar //target
    float fov //field of view
    vector2 ar //aspect ratio
    vector2 vd //view distance

type mat4
    float m11 = 1
    float m12 = 0
    float m13 = 0
    float m14 = 0
    float m21 = 0
    float m22 = 1
    float m23 = 0
    float m24 = 0
    float m31 = 0
    float m32 = 0
    float m33 = 1
    float m34 = 0
    float m41 = 0
    float m42 = 0
    float m43 = 0
    float m44 = 1

mat4_multiply(a, b) =>
    mat4.new(
     a.m11 * b.m11 + a.m12 * b.m21 + a.m13 * b.m31 + a.m14 * b.m41,
     a.m11 * b.m12 + a.m12 * b.m22 + a.m13 * b.m32 + a.m14 * b.m42,
     a.m11 * b.m13 + a.m12 * b.m23 + a.m13 * b.m33 + a.m14 * b.m43,
     a.m11 * b.m14 + a.m12 * b.m24 + a.m13 * b.m34 + a.m14 * b.m44,
     a.m21 * b.m11 + a.m22 * b.m21 + a.m23 * b.m31 + a.m24 * b.m41,
     a.m21 * b.m12 + a.m22 * b.m22 + a.m23 * b.m32 + a.m24 * b.m42,
     a.m21 * b.m13 + a.m22 * b.m23 + a.m23 * b.m33 + a.m24 * b.m43,
     a.m21 * b.m14 + a.m22 * b.m24 + a.m23 * b.m34 + a.m24 * b.m44,
     a.m31 * b.m11 + a.m32 * b.m21 + a.m33 * b.m31 + a.m34 * b.m41,
     a.m31 * b.m12 + a.m32 * b.m22 + a.m33 * b.m32 + a.m34 * b.m42,
     a.m31 * b.m13 + a.m32 * b.m23 + a.m33 * b.m33 + a.m34 * b.m43,
     a.m31 * b.m14 + a.m32 * b.m24 + a.m33 * b.m34 + a.m34 * b.m44,
     a.m41 * b.m11 + a.m42 * b.m21 + a.m43 * b.m31 + a.m44 * b.m41,
     a.m41 * b.m12 + a.m42 * b.m22 + a.m43 * b.m32 + a.m44 * b.m42,
     a.m41 * b.m13 + a.m42 * b.m23 + a.m43 * b.m33 + a.m44 * b.m43,
     a.m41 * b.m14 + a.m42 * b.m24 + a.m43 * b.m34 + a.m44 * b.m44
     )

mat4_multiply_vec4(mtx, vector) =>
    x = mtx.m11 * vector.x + mtx.m21 * vector.y + mtx.m31 * vector.z + mtx.m41 * vector.w
    y = mtx.m12 * vector.x + mtx.m22 * vector.y + mtx.m32 * vector.z + mtx.m42 * vector.w
    z = mtx.m13 * vector.x + mtx.m23 * vector.y + mtx.m33 * vector.z + mtx.m43 * vector.w
    w = mtx.m14 * vector.x + mtx.m24 * vector.y + mtx.m34 * vector.z + mtx.m44 * vector.w
    vector4.new(x, y, z, w)

mat4_scale(mtx, scale_vector) =>
    _m11 = mtx.m11 * scale_vector.x
    _m12 = mtx.m12 * scale_vector.x
    _m13 = mtx.m13 * scale_vector.x
    _m14 = mtx.m14 * scale_vector.x
    
    _m21 = mtx.m21 * scale_vector.y
    _m22 = mtx.m22 * scale_vector.y
    _m23 = mtx.m23 * scale_vector.y
    _m24 = mtx.m24 * scale_vector.y
    
    _m31 = mtx.m31 * scale_vector.z
    _m32 = mtx.m32 * scale_vector.z
    _m33 = mtx.m33 * scale_vector.z
    _m34 = mtx.m34 * scale_vector.z
    
    _m41 = mtx.m41
    _m42 = mtx.m42
    _m43 = mtx.m43
    _m44 = mtx.m44
    
    mat4.new(_m11, _m12, _m13, _m14, _m21, _m22, _m23, _m24, _m31, _m32, _m33, _m34, _m41, _m42, _m43, _m44)

mat4_translate(mtx, translation_vector) =>
    _m11 = mtx.m11
    _m12 = mtx.m12
    _m13 = mtx.m13
    _m14 = mtx.m14
    
    _m21 = mtx.m21
    _m22 = mtx.m22
    _m23 = mtx.m23
    _m24 = mtx.m24
    
    _m31 = mtx.m31
    _m32 = mtx.m32
    _m33 = mtx.m33
    _m34 = mtx.m34
    
    _m41 = mtx.m11 * translation_vector.x + mtx.m21 * translation_vector.y + mtx.m31 * translation_vector.z + mtx.m41
    _m42 = mtx.m12 * translation_vector.x + mtx.m22 * translation_vector.y + mtx.m32 * translation_vector.z + mtx.m42
    _m43 = mtx.m13 * translation_vector.x + mtx.m23 * translation_vector.y + mtx.m33 * translation_vector.z + mtx.m43
    _m44 = mtx.m14 * translation_vector.x + mtx.m24 * translation_vector.y + mtx.m34 * translation_vector.z + mtx.m44
    
    mat4.new(_m11, _m12, _m13, _m14, _m21, _m22, _m23, _m24, _m31, _m32, _m33, _m34, _m41, _m42, _m43, _m44)

rot_x(angle) =>
    c = math.cos(angle)
    s = math.sin(angle)
    mat4.new(
     1, 0, 0, 0,
     0, c, -s, 0,
     0, s, c, 0,
     0, 0, 0, 1
     )

rot_y(angle) =>
    c = math.cos(angle)
    s = math.sin(angle)
    mat4.new(
     c, 0, s, 0,
     0, 1, 0, 0,
     -s, 0, c, 0,
     0, 0, 0, 1
     )

rot_z(angle) =>
    c = math.cos(angle)
    s = math.sin(angle)
    mat4.new(
     c, -s, 0, 0,
     s, c, 0, 0,
     0, 0, 1, 0,
     0, 0, 0, 1
     )


create_transformation_matrix(position, rotation, scale) =>
    translation_matrix = mat4_translate(mat4.new(), position)
    rotation_matrix_x = rot_x(rotation.x)
    rotation_matrix_y = rot_y(rotation.y)
    rotation_matrix_z = rot_z(rotation.z)
    scale_matrix = mat4_scale(mat4.new(), scale)
    
    _transformation_matrix_1 = mat4_multiply(rotation_matrix_x, rotation_matrix_y)
    _transformation_matrix_2 = mat4_multiply(_transformation_matrix_1, rotation_matrix_z)
    _transformation_matrix_3 = mat4_multiply(_transformation_matrix_2, scale_matrix)
    transformation_matrix = mat4_multiply(_transformation_matrix_3, translation_matrix)
    transformation_matrix

radians(degree)=>
    degree * math.pi/180

ema(source)=>
    var float ema = 0.0
    var int count = 0
    count := nz(count[1]) + 1
    ema := (1.0 - 2.0 / (count + 1.0)) * nz(ema[1]) + 2.0 / (count + 1.0) * source
    ema    

perspective_transform(mesh msh, cam, obj_y_offset, true_range) =>
    transformed_vertices = array.new<vector2>(array.size(msh.v))
    minY = 1.7976931348623157e+308 
    maxY = -1.7976931348623157e+308
    fov_scale = math.tan(radians(cam.fov) / 2) * 2

    for i = 0 to array.size(msh.v) - 1
        aspect_ratio = cam.ar.x/cam.ar.y
        vertex_position = array.get(msh.v, i)
        cam_to_vertex = vector3.new(vertex_position.x - cam.pos.x, vertex_position.y - cam.pos.y, vertex_position.z - cam.pos.z)
        z = cam_to_vertex.z

        x = (cam_to_vertex.x / true_range * 5) / (z * aspect_ratio * fov_scale)
        y = (cam_to_vertex.y * true_range * 5) / (z * aspect_ratio * fov_scale)

        minY := math.min(minY, y)
        maxY := math.max(maxY, y)

        array.set(transformed_vertices, i, vector2.new(x, y))

    centerY = (minY + maxY) / 2
    for i = 0 to array.size(transformed_vertices) - 1
        vertex = array.get(transformed_vertices, i)
        array.set(transformed_vertices, i, vector2.new(vertex.x, vertex.y - centerY + obj_y_offset * syminfo.mintick * 1000))

    mesh2d.new(transformed_vertices, msh.f)

apply_transformation_matrix(vertex, matrix) =>
    vec4 = mat4_multiply_vec4(matrix, vertex)
    vec4

transform_mesh(mesh_obj, transformation_matrix) =>
    new_vertex_list = array.new<vector4>(array.size(mesh_obj.v))
    for i = 0 to array.size(mesh_obj.v) - 1
        old_vertex = array.get(mesh_obj.v, i)
        new_vertex = apply_transformation_matrix(old_vertex, transformation_matrix)
        array.set(new_vertex_list, i, new_vertex)
    mesh.new(new_vertex_list, mesh_obj.f)

process_object(obj, cam, true_range) =>
    transformation_matrix = create_transformation_matrix(obj.l.position, obj.l.theta, obj.l.scale)
    transformed_mesh = transform_mesh(obj.m, transformation_matrix)
    perspective_transform(transformed_mesh, cam, obj.l.position.y, true_range)

size(scene)=>
    size = 0
    for i = 0 to array.size(scene) - 1
        obj = array.get(scene, i)
        size += array.size(obj.f)
    size

make_poly(scene, poly_count)=>
    var poly_list = array.new<polyg>(poly_count)
    array.clear(poly_list)
    for i = 0 to array.size(scene) - 1
        poly = array.new<polyg>(array.size(array.get(scene, i).f))
        obj = array.get(scene, i)
        obj_v = obj.v
        for j = 0 to array.size(obj.f) - 1
            v1 = array.get(obj.f, j).v1
            v2 = array.get(obj.f, j).v2
            v3 = array.get(obj.f, j).v3
            array.set(poly, j, polyg.new(
             poly4.new(
             array.get(obj_v, v1).x, 
             array.get(obj_v, v2).x, 
             array.get(obj_v, v1).y, 
             array.get(obj_v, v2).y), 
             poly4.new(
             array.get(obj_v, v2).x, 
             array.get(obj_v, v3).x, 
             array.get(obj_v, v2).y, 
             array.get(obj_v, v3).y), 
             poly4.new(
             array.get(obj_v, v3).x, 
             array.get(obj_v, v1).x, 
             array.get(obj_v, v3).y, 
             array.get(obj_v, v1).y)))
        for k = 0 to array.size(poly) - 1
            array.push(poly_list, array.get(poly, k))
    poly_list

process_scene(scn, cam, true_range)=>
    new_scn = array.new<mesh2d>(array.size(scn))
    for i = 0 to array.size(scn) - 1
        new_object = process_object(array.get(scn, i), cam, true_range)
        array.set(new_scn, i, new_object)
    poly_count = size(new_scn)
    make_poly(new_scn, poly_count)

render(scene_list, Camera, offset, offxet_y)=>
    true_range = ema(high-low)
    lines = array.new<line>(500)
    time_quanta = (time[1] - last_bar_time)
    left = chart.left_visible_bar_time
    right = chart.right_visible_bar_time
    center = time + offset//(right + left)/2
    ratio = (open/(true_range/2)) / 32
    if barstate.islast
        scene_lines = process_scene(scene_list, Camera, true_range)
        for i = 0 to array.size(scene_lines) - 1
            poly = array.get(scene_lines, i)
            array.push(lines, line.new(int(center + time_quanta * poly.l1.x1 * scale_factor / ratio), poly.l1.y1 + open + offxet_y, int(center + time_quanta * poly.l1.x2 * scale_factor / ratio), poly.l1.y2 + open + offxet_y, xloc.bar_time))
            array.push(lines, line.new(int(center + time_quanta * poly.l2.x1 * scale_factor / ratio), poly.l2.y1 + open + offxet_y, int(center + time_quanta * poly.l2.x2 * scale_factor / ratio), poly.l2.y2 + open + offxet_y, xloc.bar_time))
            array.push(lines, line.new(int(center + time_quanta * poly.l3.x1 * scale_factor / ratio), poly.l3.y1 + open + offxet_y, int(center + time_quanta * poly.l3.x2 * scale_factor / ratio), poly.l3.y2 + open + offxet_y, xloc.bar_time))
    if barstate.isconfirmed
        for i = 0 to array.size(lines) - 1
            line.delete(array.get(lines, i))

pin_vertex_list = array.from(
 vector4.new(0, 0.5, 0, 1),              //0 a

 vector4.new( 0.0802,  0.3417,  0.0000, 1),  //1 b 
 vector4.new( 0.0567,  0.3417, -0.0567, 1),  //2 c 
 vector4.new( 0.0000,  0.3417, -0.0802, 1),  //3 d 
 vector4.new(-0.0567,  0.3417, -0.0567, 1), //4 e 
 vector4.new(-0.0802,  0.3417,  0.0000, 1),  //5 f 
 vector4.new(-0.0567,  0.3417,  0.0567, 1),  //6 g 
 vector4.new( 0.0000,  0.3417,  0.0802, 1),  //7 h 
 vector4.new( 0.0567,  0.3417,  0.0567, 1),  //8 i 

 vector4.new( 0.0599,  0.1667,  0.0000, 1),  //9 j
 vector4.new( 0.0424,  0.1667, -0.0424, 1),  //10 k 
 vector4.new( 0.0000,  0.1667, -0.0599, 1),  //11 l
 vector4.new(-0.0424,  0.1667, -0.0424, 1),  //12 m 
 vector4.new(-0.0599,  0.1667,  0.0000, 1),  //13 n
 vector4.new(-0.0424,  0.1667,  0.0424, 1),  //14 o 
 vector4.new( 0.0000,  0.1667,  0.0599, 1),  //15 p
 vector4.new( 0.0424,  0.1667,  0.0424, 1),  //16 q

 vector4.new( 0.1589, -0.2000,  0.0000, 1), //17 r
 vector4.new( 0.1124, -0.2000, -0.1124, 1), //18 s 
 vector4.new( 0.0000, -0.2000, -0.1589, 1), //19 t
 vector4.new(-0.1124, -0.2000, -0.1124, 1), //20 u 
 vector4.new(-0.1589, -0.2000,  0.0000, 1), //21 v
 vector4.new(-0.1124, -0.2000,  0.1124, 1), //22 w
 vector4.new( 0.0000, -0.2000,  0.1589, 1), //23 z
 vector4.new( 0.1124, -0.2000,  0.1124, 1), //24 a1

 vector4.new( 0.0677, -0.5000,  0.0000, 1), //25 b1
 vector4.new( 0.0479, -0.5000, -0.0479, 1), //26 c1
 vector4.new( 0.0000, -0.5000, -0.0677, 1), //27 d1
 vector4.new(-0.0479, -0.5000, -0.0479, 1), //28 e1
 vector4.new(-0.0677, -0.5000,  0.0000, 1), //29 f1
 vector4.new(-0.0479, -0.5000,  0.0479, 1), //30 g1
 vector4.new( 0.0000, -0.5000,  0.0677, 1), //31 h1
 vector4.new( 0.0479, -0.5000,  0.0479, 1), //32 i1
 
 vector4.new(0, -0.5, 0, 1)                 //33 h1
 )

pin_face_list = array.from(
 face.new(0, 1, 2), //0
 face.new(0, 2, 3), //1
 face.new(0, 3, 4), //2
 face.new(0, 4, 5), //3
 face.new(0, 5, 6), //4
 face.new(0, 6, 7), //5
 face.new(0, 7, 8), //6
 face.new(0, 1, 8), //7
 face.new(1, 2, 9), //8
 face.new(2, 9, 10), //9
 face.new(2, 10, 11), //10
 face.new(2, 3, 11), //11
 face.new(3, 4, 11), //12
 face.new(4, 11, 12), //13
 face.new(4, 12, 13), //14
 face.new(4, 5, 13), //15
 face.new(5, 6, 13), //16
 face.new(6, 13, 14), //17
 face.new(6, 14, 15), //18
 face.new(6, 7, 15), //19
 face.new(7, 8, 15), //20
 face.new(8, 15, 16), //21
 face.new(8, 9, 16), //22
 face.new(1, 8, 9), //23
 face.new(9, 17, 18), //24
 face.new(9, 10, 18), //25
 face.new(10, 11, 18), //26
 face.new(11, 18, 19), //27
 face.new(11, 19, 20), //28
 face.new(11, 12, 20), //29
 face.new(12, 13, 20), //30
 face.new(13, 20, 21), //31
 face.new(13, 21, 22), //32
 face.new(13, 14, 22), //33
 face.new(14, 15, 22), //34
 face.new(15, 22, 23), //35
 face.new(15, 23, 24), //36
 face.new(15, 16, 24), //37
 face.new(9, 16, 24), //38
 face.new(9, 17, 24), //39
 face.new(17, 18, 25), //40
 face.new(17, 24, 25), //41 
 face.new(18, 25, 26), //42
 face.new(18, 26, 27), //43
 face.new(18, 19, 27), //44
 face.new(19, 20, 27), //45
 face.new(20, 27, 28), //46
 face.new(20, 28, 29), //47
 face.new(20, 21, 29), //48
 face.new(21, 22, 29), //49
 face.new(22, 29, 30), //50
 face.new(22, 30, 31), //51
 face.new(22, 23, 31), //52
 face.new(23, 24, 31), //53
 face.new(24, 31, 32), //54
 face.new(24, 25, 32), //55
 face.new(25, 26, 33), //56
 face.new(26, 27, 33), //57
 face.new(27, 28, 33), //58
 face.new(28, 29, 33), //59
 face.new(29, 30, 33), //60
 face.new(30, 31, 33), //61
 face.new(31, 32, 33), //62
 face.new(25, 32, 33)  //63
 )

ball_vertex_list = array.from(
 vector4.new(0.0, -0.5, 0.0, 1),
 vector4.new(0.0, 0.5, 0.0, 1),
 vector4.new(0.17026233930306509, 0.3535533905932738, 0.3535533905932738, 1),
 vector4.new(0.24078730940376433, 3.061616997868383e-17, 0.5, 1),
 vector4.new(0.1702623393030651, -0.35355339059327373, 0.3535533905932738, 1),
 vector4.new(0.3825760036952101, 0.3535533905932738, 0.08732047630169361, 1),
 vector4.new(0.5410441730642656, 3.061616997868383e-17, 0.12348980185873357, 1),
 vector4.new(0.38257600369521017, -0.35355339059327373, 0.08732047630169362, 1),
 vector4.new(0.3068021341766003, 0.3535533905932738, -0.24466653765816737, 1),
 vector4.new(0.4338837391175582, 3.061616997868383e-17, -0.34601073581504793, 1),
 vector4.new(0.3068021341766003, -0.35355339059327373, -0.2446665376581674, 1),
 vector4.new(4.805693554381959e-17, 0.3535533905932738, -0.3924146584735999, 1),
 vector4.new(6.796277001215932e-17, 3.061616997868383e-17, -0.5549581320873712, 1),
 vector4.new(4.8056935543819596e-17, -0.35355339059327373, -0.39241465847359996, 1),
 vector4.new(-0.3068021341766002, 0.3535533905932738, -0.24466653765816745, 1),
 vector4.new(-0.43388373911755806, 3.061616997868383e-17, -0.34601073581504804, 1),
 vector4.new(-0.30680213417660024, -0.35355339059327373, -0.2446665376581675, 1),
 vector4.new(-0.3825760036952101, 0.3535533905932738, 0.08732047630169353, 1),
 vector4.new(-0.5410441730642656, 3.061616997868383e-17, 0.12348980185873344, 1),
 vector4.new(-0.38257600369521017, -0.35355339059327373, 0.08732047630169354, 1),
 vector4.new(-0.17026233930306517, 0.3535533905932738, 0.35355339059327373, 1),
 vector4.new(-0.24078730940376444, 3.061616997868383e-17, 0.49999999999999994, 1),
 vector4.new(-0.1702623393030652, -0.35355339059327373, 0.3535533905932738, 1)
 )

ball_face_list = array.from(
 face.new(2, 5, 1),
 face.new(2, 3, 6),
 face.new(3, 4, 7),
 face.new(7, 4, 0),
 face.new(5, 8, 1),
 face.new(5, 6, 9),
 face.new(6, 7, 10),
 face.new(10, 7, 0),
 face.new(8, 11, 1),
 face.new(8, 9, 12),
 face.new(9, 10, 13),
 face.new(13, 10, 0),
 face.new(11, 14, 1),
 face.new(11, 12, 15),
 face.new(12, 13, 16),
 face.new(16, 13, 0),
 face.new(14, 17, 1),
 face.new(14, 15, 18),
 face.new(15, 16, 19),
 face.new(19, 16, 0),
 face.new(17, 20, 1),
 face.new(17, 18, 21),
 face.new(18, 19, 22),
 face.new(22, 19, 0),
 face.new(20, 2, 1),
 face.new(20, 21, 3),
 face.new(21, 22, 4),
 face.new(4, 22, 0)
 )

Arwing_vertex_list = array.from(
 vector4.new(-0.157674, 0.658789, 0.636509, 1),
 vector4.new(0.157282, 1.19168, -0.64882, 1),
 vector4.new(-0.157674, 1.19168, -0.64882, 1),
 vector4.new(0.157282, 0.658789, 0.63651, 1),
 vector4.new(0.354133, 0.7358, -0.273302, 1),
 vector4.new(-0.354524, 0.7358, -0.273302, 1),
 vector4.new(-1.22067, 0.477053, -0.584587, 1),
 vector4.new(-0.866336, 0.089177, -0.448857, 1),
 vector4.new(-1.88996, -0.0307165, -0.482857, 1),
 vector4.new(-0.630116, 0.4804, -0.506169, 1),
 vector4.new(-0.354524, 0.00868859, -0.484527, 1),
 vector4.new(-0.000195773, 0.11069, -0.844209, 1),
 vector4.new(-0.000195815, 0.244741, -0.495345, 1),
 vector4.new(0.629724, 0.4804, -0.506169, 1),
 vector4.new(-0.000195811, 0.75586, -0.518657, 1),
 vector4.new(-0.000195624, 0.804545, -2.0578, 1),
 vector4.new(-0.354524, 0.727271, -0.280933, 1),
 vector4.new(-0.157282, 0.687595, 0.588189, 1),
 vector4.new(0.157677, 0.687601, 0.587795, 1),
 vector4.new(0.000197441, 0.687598, 3.18898, 1),
 vector4.new(-0.275391, 0.517739, 2.05394, 1),
 vector4.new(-0.157283, 0.321096, 2.06269, 1),
 vector4.new(-0.354133, 0.0121655, 0.460955, 1),
 vector4.new(-0.550983, 0.167731, 0.414467, 1),
 vector4.new(-0.866335, 1.4049, -1.84841, 1),
 vector4.new(-1.22027, 0.167731, 0.414467, 1),
 vector4.new(-0.865944, 0.237261, 1.9486, 1),
 vector4.new(0.354133, 0.0086955, -0.484921, 1),
 vector4.new(0.865944, 0.089177, -0.448856, 1),
 vector4.new(1.22027, 0.47706, -0.58498, 1),
 vector4.new(0.865944, 1.40491, -1.8488, 1),
 vector4.new(0.550985, 0.167731, 0.414467, 1),
 vector4.new(0.866338, 0.237268, 1.94821, 1),
 vector4.new(1.22067, 0.167731, 0.414467, 1),
 vector4.new(0.354527, 0.0121655, 0.460955, 1),
 vector4.new(-0.078541, 0.16012, 1.99135, 1),
 vector4.new(0.0789372, 0.16012, 1.99135, 1),
 vector4.new(0.157676, 0.321096, 2.06269, 1),
 vector4.new(0.275787, 0.517739, 2.05394, 1),
 vector4.new(0.354133, 0.727271, -0.280933, 1),
 vector4.new(0.157282, 1.22255, -0.658122, 1),
 vector4.new(-0.157674, 1.22255, -0.658122, 1),
 vector4.new(1.88957, -0.0307096, -0.48325, 1),
 vector4.new(0.846655, -0.240109, 0.117496, 1),
 vector4.new(1.20098, -0.161432, 1.84828, 1),
 vector4.new(1.51555, -0.240109, 0.117496, 1),
 vector4.new(1.20059, -0.643821, -0.10065, 1),
 vector4.new(1.20059, -0.3005, -1.2196, 1),
 vector4.new(1.12185, 0.173013, -0.334768, 1),
 vector4.new(1.23996, -0.220274, -0.316868, 1),
 vector4.new(1.12185, -0.220274, -0.316868, 1),
 vector4.new(1.23996, 0.173013, -0.334768, 1),
 vector4.new(1.23996, 0.190914, 0.0585201, 1),
 vector4.new(1.23996, -0.191557, 0.312473, 1),
 vector4.new(1.12185, -0.191557, 0.312473, 1),
 vector4.new(1.12185, 0.190914, 0.0585201, 1),
 vector4.new(0.839568, -0.0834101, -1.2717, 1),
 vector4.new(1.36988, 0.0463139, -0.945355, 1),
 vector4.new(1.06595, -0.450375, -1.94557, 1),
 vector4.new(1.36791, -0.0698241, -0.924162, 1),
 vector4.new(1.49232, -0.406907, -1.66287, 1),
 vector4.new(1.4935, -0.329482, -1.67687, 1),
 vector4.new(0.845866, -0.09343, -1.28408, 1),
 vector4.new(1.37894, -0.0812873, -0.944052, 1),
 vector4.new(1.06476, -0.45752, -1.94215, 1),
 vector4.new(1.35413, -0.152573, -0.898446, 1),
 vector4.new(1.50098, -0.495096, -1.66363, 1),
 vector4.new(1.50256, -0.417671, -1.67763, 1),
 vector4.new(1.35768, 0.0308721, -0.962951, 1),
 vector4.new(1.80413, 0.130054, -0.153211, 1),
 vector4.new(1.49705, -0.342761, -1.68301, 1),
 vector4.new(1.33996, 0.425713, -0.553593, 1),
 vector4.new(0.901772, 0.303041, -0.832956, 1),
 vector4.new(1.33366, 0.0773056, -0.49041, 1),
 vector4.new(1.35413, -0.162688, -0.927762, 1),
 vector4.new(1.02618, -0.0772801, -1.14992, 1),
 vector4.new(1.49429, -0.498002, -1.65502, 1),
 vector4.new(1.09232, -0.458329, -1.91854, 1),
 vector4.new(1.37343, -0.52054, -2.23267, 1),
 vector4.new(1.60768, -0.519131, -2.20075, 1),
 vector4.new(1.76791, -0.457576, -1.62517, 1),
 vector4.new(1.89075, -0.636746, -1.9386, 1),
 vector4.new(1.7624, -0.742832, -3.63325, 1),
 vector4.new(-1.51594, -0.239722, 0.117897, 1),
 vector4.new(-1.20059, -0.161432, 1.84828, 1),
 vector4.new(-0.846652, -0.239722, 0.117897, 1),
 vector4.new(-1.20098, -0.643828, -0.100256, 1),
 vector4.new(-1.20098, -0.3005, -1.2196, 1),
 vector4.new(-1.24035, 0.173006, -0.334375, 1),
 vector4.new(-1.12224, -0.220281, -0.316475, 1),
 vector4.new(-1.24035, -0.220281, -0.316475, 1),
 vector4.new(-1.12224, 0.173006, -0.334375, 1),
 vector4.new(-1.12224, 0.190907, 0.0589135, 1),
 vector4.new(-1.12224, -0.191557, 0.312473, 1),
 vector4.new(-1.24035, 0.190907, 0.0589135, 1),
 vector4.new(-1.24035, -0.191557, 0.312473, 1),
 vector4.new(-1.50295, -0.417284, -1.67723, 1),
 vector4.new(-1.37894, -0.0812942, -0.943658, 1),
 vector4.new(-0.845863, -0.0934369, -1.28369, 1),
 vector4.new(-1.35453, -0.152972, -0.89806, 1),
 vector4.new(-1.06476, -0.45752, -1.94215, 1),
 vector4.new(-1.50138, -0.494709, -1.66323, 1),
 vector4.new(-1.49389, -0.329489, -1.67648, 1),
 vector4.new(-1.37027, 0.046307, -0.944961, 1),
 vector4.new(-0.839565, -0.083417, -1.27131, 1),
 vector4.new(-1.36791, -0.0698241, -0.924163, 1),
 vector4.new(-1.06634, -0.450382, -1.94518, 1),
 vector4.new(-1.49232, -0.406914, -1.66248, 1),
 vector4.new(-1.80452, 0.130047, -0.152818, 1),
 vector4.new(-1.49704, -0.342768, -1.68262, 1),
 vector4.new(-1.76791, -0.457583, -1.62478, 1),
 vector4.new(-1.35807, 0.0308721, -0.962952, 1),
 vector4.new(-1.33996, 0.425713, -0.553593, 1),
 vector4.new(-1.33366, 0.0772987, -0.490016, 1),
 vector4.new(-1.35453, -0.162688, -0.927762, 1),
 vector4.new(-1.49429, -0.498009, -1.65463, 1),
 vector4.new(-1.89114, -0.636746, -1.9386, 1),
 vector4.new(-1.37382, -0.520547, -2.23228, 1),
 vector4.new(-1.76279, -0.742839, -3.63285, 1),
 vector4.new(-1.60767, -0.519131, -2.20075, 1),
 vector4.new(-1.09271, -0.458329, -1.91854, 1),
 vector4.new(-1.02618, -0.077287, -1.14953, 1),
 vector4.new(-0.90177, 0.303041, -0.832956, 1)
 )

Arwing_face_list = array.from(
 face.new(0, 1, 2),
 face.new(0, 3, 1),
 face.new(3, 4, 1),
 face.new(0, 2, 5),
 face.new(6, 7, 8),
 face.new(9, 7, 6),
 face.new(9, 10, 7),
 face.new(9, 11, 10),
 face.new(9, 12, 11),
 face.new(9, 13, 12),
 face.new(13, 9, 14),
 face.new(9, 15, 14),
 face.new(9, 16, 15),
 face.new(17, 16, 9),
 face.new(16, 17, 18),
 face.new(17, 19, 18),
 face.new(20, 19, 17),
 face.new(19, 20, 21),
 face.new(21, 20, 9),
 face.new(9, 20, 17),
 face.new(21, 9, 22),
 face.new(9, 23, 22),
 face.new(23, 9, 24),
 face.new(6, 24, 9),
 face.new(25, 24, 6),
 face.new(26, 24, 25),
 face.new(26, 23, 24),
 face.new(25, 23, 26),
 face.new(25, 7, 23),
 face.new(8, 7, 25),
 face.new(8, 25, 6),
 face.new(7, 22, 23),
 face.new(7, 10, 22),
 face.new(10, 27, 22),
 face.new(10, 11, 27),
 face.new(13, 27, 11),
 face.new(13, 28, 27),
 face.new(13, 29, 28),
 face.new(13, 30, 29),
 face.new(31, 30, 13),
 face.new(32, 30, 31),
 face.new(32, 33, 30),
 face.new(31, 33, 32),
 face.new(31, 28, 33),
 face.new(34, 28, 31),
 face.new(27, 28, 34),
 face.new(22, 27, 34),
 face.new(22, 34, 35),
 face.new(35, 34, 36),
 face.new(37, 36, 34),
 face.new(37, 35, 36),
 face.new(35, 37, 21),
 face.new(21, 37, 19),
 face.new(19, 37, 38),
 face.new(37, 13, 38),
 face.new(37, 34, 13),
 face.new(34, 31, 13),
 face.new(18, 38, 13),
 face.new(19, 38, 18),
 face.new(18, 13, 39),
 face.new(15, 39, 13),
 face.new(39, 15, 40),
 face.new(41, 40, 15),
 face.new(40, 41, 16),
 face.new(16, 41, 15),
 face.new(40, 16, 39),
 face.new(16, 18, 39),
 face.new(15, 13, 14),
 face.new(21, 22, 35),
 face.new(28, 42, 33),
 face.new(29, 42, 28),
 face.new(29, 33, 42),
 face.new(33, 29, 30),
 face.new(12, 13, 11),
 face.new(43, 44, 45),
 face.new(43, 46, 44),
 face.new(43, 47, 46),
 face.new(43, 45, 47),
 face.new(45, 46, 47),
 face.new(44, 46, 45),
 face.new(48, 49, 50),
 face.new(49, 48, 51),
 face.new(52, 49, 51),
 face.new(53, 49, 52),
 face.new(52, 54, 53),
 face.new(54, 52, 55),
 face.new(54, 55, 48),
 face.new(54, 48, 50),
 face.new(56, 57, 58),
 face.new(57, 56, 59),
 face.new(56, 60, 59),
 face.new(56, 58, 60),
 face.new(61, 60, 58),
 face.new(58, 57, 61),
 face.new(62, 63, 64),
 face.new(63, 62, 65),
 face.new(62, 66, 65),
 face.new(62, 64, 66),
 face.new(67, 66, 64),
 face.new(64, 63, 67),
 face.new(68, 69, 70),
 face.new(69, 68, 71),
 face.new(72, 71, 68),
 face.new(71, 72, 73),
 face.new(72, 74, 73),
 face.new(72, 75, 74),
 face.new(72, 68, 75),
 face.new(68, 74, 75),
 face.new(74, 68, 70),
 face.new(74, 70, 76),
 face.new(70, 77, 76),
 face.new(77, 70, 78),
 face.new(78, 70, 79),
 face.new(70, 80, 79),
 face.new(70, 69, 80),
 face.new(74, 80, 69),
 face.new(74, 76, 80),
 face.new(76, 81, 80),
 face.new(78, 81, 76),
 face.new(78, 82, 81),
 face.new(78, 79, 82),
 face.new(79, 81, 82),
 face.new(79, 80, 81),
 face.new(77, 78, 76),
 face.new(73, 74, 69),
 face.new(71, 73, 69),
 face.new(83, 84, 85),
 face.new(84, 83, 86),
 face.new(83, 87, 86),
 face.new(83, 85, 87),
 face.new(85, 86, 87),
 face.new(86, 85, 84),
 face.new(88, 89, 90),
 face.new(89, 88, 91),
 face.new(92, 89, 91),
 face.new(93, 89, 92),
 face.new(94, 93, 92),
 face.new(93, 94, 95),
 face.new(95, 94, 88),
 face.new(95, 88, 90),
 face.new(96, 97, 98),
 face.new(97, 99, 98),
 face.new(99, 100, 98),
 face.new(101, 100, 99),
 face.new(96, 100, 101),
 face.new(96, 98, 100),
 face.new(102, 103, 104),
 face.new(103, 105, 104),
 face.new(105, 106, 104),
 face.new(107, 106, 105),
 face.new(102, 106, 107),
 face.new(102, 104, 106),
 face.new(108, 109, 110),
 face.new(108, 111, 109),
 face.new(108, 112, 111),
 face.new(112, 108, 113),
 face.new(108, 114, 113),
 face.new(108, 110, 114),
 face.new(110, 115, 114),
 face.new(116, 115, 110),
 face.new(116, 117, 115),
 face.new(116, 118, 117),
 face.new(116, 119, 118),
 face.new(116, 110, 119),
 face.new(110, 109, 119),
 face.new(119, 109, 117),
 face.new(109, 120, 117),
 face.new(109, 115, 120),
 face.new(111, 115, 109),
 face.new(114, 115, 111),
 face.new(111, 121, 114),
 face.new(122, 121, 111),
 face.new(114, 121, 122),
 face.new(114, 122, 113),
 face.new(112, 113, 122),
 face.new(111, 112, 122),
 face.new(115, 117, 120),
 face.new(118, 119, 117)
 )

list = input.string("Ball", "3D Scene", ["Pin", "Ball", "Arwing", "Pin and Ball"])

offset_x = input.int(0, "offset x") * (time-time[1])
offset_y = input.float(0, "offset y")
object_x = input.float(0)
object_y = input.float(0)
object_z = input.float(0)

object_theta_x = input.float(0)
object_theta_y = input.float(0)
object_theta_z = input.float(0)
  
object_scale_x = input.float(0.5)
object_scale_y = input.float(0.5)
object_scale_z = input.float(0.5)

x_pos = input.float(0)
y_pos = input.float(0)
z_pos = input.float(-2)

x_look = input.float(0)
y_look = input.float(0)
z_look = input.float(0)

fov = input.float(45)

near = input.float(0.1)
far = input.float(20)

Camera = camera.new(vector3.new(x_pos, y_pos, z_pos), vector3.new(x_look, y_look, z_look), fov, vector2.new(1, 1), vector2.new(near, far))

pin_mesh = mesh.new(pin_vertex_list, pin_face_list)
ball_mesh = mesh.new(ball_vertex_list, ball_face_list)
arwing_mesh = mesh.new(Arwing_vertex_list, Arwing_face_list)

pin = object.new(pin_mesh, location.new(vector3.new(object_x, object_y, object_z), vector3.new(object_theta_x, object_theta_y, object_theta_z), vector3.new(object_scale_x, object_scale_y, object_scale_z)))
pin_offset = object.new(pin_mesh, location.new(vector3.new(object_x + 1, object_y, object_z), vector3.new(object_theta_x, object_theta_y, object_theta_z), vector3.new(object_scale_x, object_scale_y, object_scale_z)))
ball = object.new(ball_mesh, location.new(vector3.new(object_x, object_y, object_z), vector3.new(object_theta_x, object_theta_y, object_theta_z), vector3.new(object_scale_x, object_scale_y, object_scale_z)))
arwing = object.new(arwing_mesh, location.new(vector3.new(object_x, object_y, object_z), vector3.new(object_theta_x, object_theta_y, object_theta_z), vector3.new(object_scale_x, object_scale_y, object_scale_z)))

pin_scene = array.from(pin)
ball_scene = array.from(ball)
arwing_scene = array.from(arwing)
pin_ball_scene = array.from(pin_offset, ball)

scene_list = switch list
    "Pin" => pin_scene
    "Ball" => ball_scene
    "Arwing" => arwing_scene
    "Pin and Ball" => pin_ball_scene
    
render(scene_list, Camera, offset_x, offset_y)

// plot(ratio)
//python program to convert .obj files into 3D files for the engine
// def parse_obj(file_path):
//     vertices = []
//     faces = []

//     with open(file_path, 'r') as file:
//         for line in file:
//             if line.startswith('v '):
//                 coords = list(map(float, line[2:].split()))
//                 vertices.append(coords)
//             elif line.startswith('f '):
//                 indices = [int(s.split('/')[0]) - 1 for s in line[2:].split()]
//                 faces.append(indices)

//     return vertices, faces

// def convert_to_custom_format(vertices, faces, vertex_var_name, face_var_name):
//     vertex_lines = [f"vector4.new({v[0]}, {v[1]}, {v[2]}, 1)," for v in vertices]
//     vertex_data = f"{vertex_var_name} = array.from(\n " + "\n ".join(vertex_lines) + "\n)"

//     face_lines = [f"face.new({f[0]}, {f[1]}, {f[2]})," for f in faces]
//     face_data = f"{face_var_name} = array.from(\n " + "\n ".join(face_lines) + "\n)"

//     return vertex_data + "\n\n" + face_data

// def main():
//     input_obj_file = "C:/object.obj"
//     output_custom_file = "C:/object.txt"
//     vertex_var_name = "object_vertex_list"
//     face_var_name = "object_face_list"

//     vertices, faces = parse_obj(input_obj_file)
//     custom_data = convert_to_custom_format(vertices, faces, vertex_var_name, face_var_name)

//     with open(output_custom_file, 'w') as output_file:
//         output_file.write(custom_data)

// if __name__ == "__main__":
//     main()
