├── README.md
├── UNLICENSE
├── src
├── assets
│ └── bg.jpg
├── common.nim
├── core.nim
├── data.nim
└── vim3.nim
├── vim3.gif
└── vim3.nimble
/README.md:
--------------------------------------------------------------------------------
1 | ## Vim³
2 |
3 | Most people use vim in two stupid dimensions. But not me. I use it in three:
4 |
5 |
6 |
7 |
8 |
9 | To run it, [install Nim](https://nim-lang.org/install.html), and from this repo do:
10 |
11 | ```
12 | nimble run vim3
13 | ```
14 |
15 | Once you're ready to start using it as your main editor, do:
16 |
17 | ```
18 | nimble install paravim
19 | nimble install
20 | ```
21 |
22 | As long as `~/.nimble/bin` is on your PATH, you will now be able to open files like this:
23 |
24 | ```
25 | vim3 path/to/myfile.txt
26 | ```
27 |
28 | ## Q & A
29 |
30 | ### How do i acquire your power?
31 |
32 | It's not that hard
33 |
34 | ### How do i stop the cube from spinning
35 |
36 | no
37 |
38 | ### I don't even have vim installed, how is this possible?
39 |
40 | It's using [paravim](https://github.com/paranim/paravim) which has a real copy of vim built in
41 |
42 | ### Which OS does it work on?
43 |
44 | All of them pretty much
45 |
46 | ### Why can't i run it on linux?
47 |
48 | Could be you need opengl libraries, try `sudo apt install xorg-dev libgl1-mesa-dev`
49 |
50 | You might also need to do `sudo apt install libtinfo5`
51 |
52 | ### I use arch btw
53 |
54 | Try this: `sudo ln -s /usr/lib/libtinfo.so.6 /usr/lib/libtinfo.so.5`
55 |
--------------------------------------------------------------------------------
/UNLICENSE:
--------------------------------------------------------------------------------
1 | This is free and unencumbered software released into the public domain.
2 |
3 | Anyone is free to copy, modify, publish, use, compile, sell, or
4 | distribute this software, either in source code form or as a compiled
5 | binary, for any purpose, commercial or non-commercial, and by any
6 | means.
7 |
8 | In jurisdictions that recognize copyright laws, the author or authors
9 | of this software dedicate any and all copyright interest in the
10 | software to the public domain. We make this dedication for the benefit
11 | of the public at large and to the detriment of our heirs and
12 | successors. We intend this dedication to be an overt act of
13 | relinquishment in perpetuity of all present and future rights to this
14 | software under copyright law.
15 |
16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19 | IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
20 | OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
21 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 | OTHER DEALINGS IN THE SOFTWARE.
23 |
24 | For more information, please refer to
25 |
--------------------------------------------------------------------------------
/src/assets/bg.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oakes/vim_cubed/ea33fc71ae8d27351978e7e37057e69e3eb629e3/src/assets/bg.jpg
--------------------------------------------------------------------------------
/src/common.nim:
--------------------------------------------------------------------------------
1 | import paranim/gl, paranim/gl/uniforms, paranim/gl/attributes
2 | import nimgl/opengl
3 | import glm
4 | from sequtils import map
5 | from std/math import nil
6 | import paranim/math as pmath
7 |
8 | type
9 | Game* = object of RootGame
10 | deltaTime*: float
11 | totalTime*: float
12 | frameWidth*: int
13 | frameHeight*: int
14 |
15 | proc project*[UniT, AttrT](entity: var Entity[UniT, AttrT], left: GLfloat, right: GLfloat, bottom: GLfloat, top: GLfloat, near: GLfloat, far: GLfloat) =
16 | entity.uniforms.u_matrix.project(left, right, bottom, top, near, far)
17 |
18 | proc project*[UniT, AttrT](entity: var Entity[UniT, AttrT], fieldOfView: GLfloat, aspect: GLfloat, near: GLfloat, far: GLfloat) =
19 | entity.uniforms.u_matrix.project(fieldOfView, aspect, near, far)
20 |
21 | proc translate*[UniT, AttrT](entity: var Entity[UniT, AttrT], x: GLfloat, y: GLfloat, z: GLfloat) =
22 | entity.uniforms.u_matrix.translate(x, y, z)
23 |
24 | proc scale*[UniT, AttrT](entity: var Entity[UniT, AttrT], x: GLfloat, y: GLfloat, z: GLfloat) =
25 | entity.uniforms.u_matrix.scale(x, y, z)
26 |
27 | proc rotateX*[UniT, AttrT](entity: var Entity[UniT, AttrT], angle: GLFloat) =
28 | entity.uniforms.u_matrix.rotateX(angle)
29 |
30 | proc rotateY*[UniT, AttrT](entity: var Entity[UniT, AttrT], angle: GLFloat) =
31 | entity.uniforms.u_matrix.rotateY(angle)
32 |
33 | proc rotateZ*[UniT, AttrT](entity: var Entity[UniT, AttrT], angle: GLFloat) =
34 | entity.uniforms.u_matrix.rotateZ(angle)
35 |
36 | proc invert*[UniT, AttrT](entity: var Entity[UniT, AttrT], cam: Mat4x4[GLfloat]) =
37 | entity.uniforms.u_matrix.invert(cam)
38 |
39 | proc degToRad*(degrees: GLfloat): GLfloat =
40 | (degrees * math.PI) / 180f
41 |
42 | # textured 3D entity
43 |
44 | const threeDTextureVertexShader* =
45 | """
46 | #version 330
47 | uniform mat4 u_matrix;
48 | in vec4 a_position;
49 | in vec2 a_texcoord;
50 | out vec2 v_texcoord;
51 | void main()
52 | {
53 | gl_Position = u_matrix * a_position;
54 | v_texcoord = a_texcoord;
55 | v_texcoord.y = 1.0 - v_texcoord.y; // flip y axis
56 | }
57 | """
58 |
59 | const threeDTextureFragmentShader* =
60 | """
61 | #version 330
62 | precision mediump float;
63 | uniform sampler2D u_texture;
64 | in vec2 v_texcoord;
65 | out vec4 outColor;
66 | void main()
67 | {
68 | outColor = texture(u_texture, v_texcoord);
69 | }
70 | """
71 |
72 |
--------------------------------------------------------------------------------
/src/core.nim:
--------------------------------------------------------------------------------
1 | import nimgl/opengl
2 | import paranim/gl, paranim/gl/uniforms, paranim/gl/attributes, paranim/gl/entities
3 | import paranim/math as pmath
4 | import common, data
5 | from bitops import bitor
6 | from std/math import nil
7 | import glm
8 | from paravim/core as paravim_core import nil
9 | from paravim import nil
10 | import stb_image/read as stbi
11 | from pararules import nil
12 |
13 | type
14 | ThreeDMetaTextureEntityUniforms = tuple[u_matrix: Uniform[Mat4x4[GLfloat]], u_texture: Uniform[RenderToTexture[GLubyte, Game]]]
15 | ThreeDMetaTextureEntityAttributes = tuple[a_position: Attribute[GLfloat], a_texcoord: Attribute[GLfloat]]
16 | ThreeDMetaTextureEntity = object of ArrayEntity[ThreeDMetaTextureEntityUniforms, ThreeDMetaTextureEntityAttributes]
17 | UncompiledThreeDMetaTextureEntity = object of UncompiledEntity[ThreeDMetaTextureEntity, ThreeDMetaTextureEntityUniforms, ThreeDMetaTextureEntityAttributes]
18 |
19 | proc initThreeDMetaTextureEntity(posData: openArray[GLfloat], texcoordData: openArray[GLfloat], image: RenderToTexture[GLubyte, Game]): UncompiledThreeDMetaTextureEntity =
20 | result.vertexSource = threeDTextureVertexShader
21 | result.fragmentSource = threeDTextureFragmentShader
22 | # position
23 | var position = Attribute[GLfloat](size: 3, iter: 1)
24 | new(position.data)
25 | position.data[] = @posData
26 | # texcoord
27 | var texcoord = Attribute[GLfloat](size: 2, iter: 1, normalize: true)
28 | new(texcoord.data)
29 | texcoord.data[] = @texcoordData
30 | # set attrs and unis
31 | result.attributes = (a_position: position, a_texcoord: texcoord)
32 | result.uniforms = (
33 | u_matrix: Uniform[Mat4x4[GLfloat]](data: mat4f(1)),
34 | u_texture: Uniform[RenderToTexture[GLubyte, Game]](data: image)
35 | )
36 |
37 | var
38 | entity: ThreeDMetaTextureEntity
39 | imageEntity: ImageEntity
40 | rx = degToRad(180f)
41 | ry = degToRad(40f)
42 | imageWidth: int
43 | imageHeight: int
44 |
45 | const image = staticRead("assets/bg.jpg")
46 |
47 | proc init*(game: var Game) =
48 | doAssert glInit()
49 |
50 | glEnable(GL_BLEND)
51 | glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
52 | glEnable(GL_DEPTH_TEST)
53 |
54 | let
55 | windowWidth = pararules.query(paravim_core.session, paravim_core.rules.getWindow).windowWidth
56 | cubeSize = int(windowWidth / 2)
57 | paravim_core.onWindowResize(cubeSize, cubeSize)
58 | paravim_core.insert(paravim_core.session, paravim_core.Global, paravim_core.AsciiArt, "")
59 |
60 | let outerImage = RenderToTexture[GLubyte, Game](
61 | opts: TextureOpts(
62 | mipLevel: 0,
63 | internalFmt: GL_RGBA,
64 | width: GLsizei(cubeSize),
65 | height: GLsizei(cubeSize),
66 | border: 0,
67 | srcFmt: GL_RGBA
68 | ),
69 | params: @[
70 | (GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE),
71 | (GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE),
72 | (GL_TEXTURE_MIN_FILTER, GL_LINEAR)
73 | ],
74 | render: proc (game: Game) =
75 | glDisable(GL_CULL_FACE)
76 | discard paravim.tick(game, true)
77 | glEnable(GL_CULL_FACE)
78 | )
79 |
80 | entity = compile(game, initThreeDMetaTextureEntity(cube, cubeTexcoords, outerImage))
81 |
82 | var
83 | channels: int
84 | data: seq[uint8]
85 | data = stbi.loadFromMemory(cast[seq[uint8]](image), imageWidth, imageHeight, channels, stbi.RGBA)
86 | imageEntity = compile(game, initImageEntity(data, imageWidth, imageHeight))
87 |
88 | proc tick*(game: Game) =
89 | glClearColor(1f, 1f, 1f, 1f)
90 | glClear(GLbitfield(bitor(GL_COLOR_BUFFER_BIT.ord, GL_DEPTH_BUFFER_BIT.ord)))
91 | glViewport(0, 0, GLsizei(game.frameWidth), GLsizei(game.frameHeight))
92 |
93 | block:
94 | glDisable(GL_CULL_FACE)
95 | let
96 | frameRatio = game.frameWidth.float / game.frameHeight.float
97 | imageRatio = imageWidth.float / imageHeight.float
98 | (width, height) =
99 | if frameRatio > imageRatio:
100 | (game.frameWidth.float, game.frameWidth.float * (imageHeight.float / imageWidth.float))
101 | else:
102 | (game.frameHeight.float * imageRatio, game.frameHeight.float)
103 | var e = imageEntity
104 | e.project(float(game.frameWidth), float(game.frameHeight))
105 | e.translate(0f, 0f)
106 | e.scale(width, height)
107 | render(game, e)
108 |
109 | var camera = mat4f(1)
110 | camera.translate(0f, 0f, 2f)
111 | camera.lookAt(vec3(0f, 0f, 0f), vec3(0f, 1f, 0f))
112 |
113 | var e = entity
114 | e.project(degToRad(60f), float(game.frameWidth) / float(game.frameHeight), 1f, 2000f)
115 | e.invert(camera)
116 | e.rotateX(rx)
117 | e.rotateY(ry)
118 | e.scale(1.15f, 1.15f, 1.15f)
119 | render(game, e)
120 |
121 | rx += 0.5f * game.deltaTime
122 | ry += 0.5f * game.deltaTime
123 |
124 |
--------------------------------------------------------------------------------
/src/data.nim:
--------------------------------------------------------------------------------
1 | const cube* = [
2 | -0.5f, -0.5f, -0.5f,
3 | -0.5f, 0.5f, -0.5f,
4 | 0.5f, -0.5f, -0.5f,
5 | -0.5f, 0.5f, -0.5f,
6 | 0.5f, 0.5f, -0.5f,
7 | 0.5f, -0.5f, -0.5f,
8 |
9 | -0.5f, -0.5f, 0.5f,
10 | 0.5f, -0.5f, 0.5f,
11 | -0.5f, 0.5f, 0.5f,
12 | -0.5f, 0.5f, 0.5f,
13 | 0.5f, -0.5f, 0.5f,
14 | 0.5f, 0.5f, 0.5f,
15 |
16 | -0.5f, 0.5f, -0.5f,
17 | -0.5f, 0.5f, 0.5f,
18 | 0.5f, 0.5f, -0.5f,
19 | -0.5f, 0.5f, 0.5f,
20 | 0.5f, 0.5f, 0.5f,
21 | 0.5f, 0.5f, -0.5f,
22 |
23 | -0.5f, -0.5f, -0.5f,
24 | 0.5f, -0.5f, -0.5f,
25 | -0.5f, -0.5f, 0.5f,
26 | -0.5f, -0.5f, 0.5f,
27 | 0.5f, -0.5f, -0.5f,
28 | 0.5f, -0.5f, 0.5f,
29 |
30 | -0.5f, -0.5f, -0.5f,
31 | -0.5f, -0.5f, 0.5f,
32 | -0.5f, 0.5f, -0.5f,
33 | -0.5f, -0.5f, 0.5f,
34 | -0.5f, 0.5f, 0.5f,
35 | -0.5f, 0.5f, -0.5f,
36 |
37 | 0.5f, -0.5f, -0.5f,
38 | 0.5f, 0.5f, -0.5f,
39 | 0.5f, -0.5f, 0.5f,
40 | 0.5f, -0.5f, 0.5f,
41 | 0.5f, 0.5f, -0.5f,
42 | 0.5f, 0.5f, 0.5f,
43 | ]
44 |
45 | const cubeTexcoords* = [
46 | 0f, 0f,
47 | 0f, 1f,
48 | 1f, 0f,
49 | 0f, 1f,
50 | 1f, 1f,
51 | 1f, 0f,
52 |
53 | 0f, 0f,
54 | 0f, 1f,
55 | 1f, 0f,
56 | 1f, 0f,
57 | 0f, 1f,
58 | 1f, 1f,
59 |
60 | 0f, 0f,
61 | 0f, 1f,
62 | 1f, 0f,
63 | 0f, 1f,
64 | 1f, 1f,
65 | 1f, 0f,
66 |
67 | 0f, 0f,
68 | 0f, 1f,
69 | 1f, 0f,
70 | 1f, 0f,
71 | 0f, 1f,
72 | 1f, 1f,
73 |
74 | 0f, 0f,
75 | 0f, 1f,
76 | 1f, 0f,
77 | 0f, 1f,
78 | 1f, 1f,
79 | 1f, 0f,
80 |
81 | 0f, 0f,
82 | 0f, 1f,
83 | 1f, 0f,
84 | 1f, 0f,
85 | 0f, 1f,
86 | 1f, 1f,
87 | ]
88 |
--------------------------------------------------------------------------------
/src/vim3.nim:
--------------------------------------------------------------------------------
1 | import nimgl/glfw
2 | import common
3 | from core import nil
4 | from paravim import nil
5 | from os import nil
6 |
7 | var game = Game()
8 |
9 | proc keyCallback(window: GLFWWindow, key: int32, scancode: int32, action: int32, mods: int32) {.cdecl.} =
10 | paravim.keyCallback(window, key, scancode, action, mods)
11 |
12 | proc charCallback(window: GLFWWindow, codepoint: uint32) {.cdecl.} =
13 | paravim.charCallback(window, codepoint)
14 |
15 | proc frameSizeCallback(window: GLFWWindow, width: int32, height: int32) {.cdecl.} =
16 | game.frameWidth = width
17 | game.frameHeight = height
18 |
19 | when isMainModule:
20 | doAssert glfwInit()
21 |
22 | glfwWindowHint(GLFWContextVersionMajor, 3)
23 | glfwWindowHint(GLFWContextVersionMinor, 3)
24 | glfwWindowHint(GLFWOpenglForwardCompat, GLFW_TRUE) # Used for Mac
25 | glfwWindowHint(GLFWOpenglProfile, GLFW_OPENGL_CORE_PROFILE)
26 | glfwWindowHint(GLFWResizable, GLFW_TRUE)
27 |
28 | let w: GLFWWindow = glfwCreateWindow(1024, 768, "Vim³ - You can begin by typing `:e path/to/myfile.txt`")
29 | if w == nil:
30 | quit(-1)
31 |
32 | w.makeContextCurrent()
33 | glfwSwapInterval(1)
34 |
35 | discard w.setKeyCallback(keyCallback)
36 | discard w.setCharCallback(charCallback)
37 | discard w.setFramebufferSizeCallback(frameSizeCallback)
38 |
39 | var width, height: int32
40 | w.getFramebufferSize(width.addr, height.addr)
41 | w.frameSizeCallback(width, height)
42 |
43 | let params = os.commandLineParams()
44 | paravim.init(game, w, params)
45 | core.init(game)
46 |
47 | game.totalTime = glfwGetTime()
48 |
49 | while not w.windowShouldClose:
50 | let ts = glfwGetTime()
51 | game.deltaTime = ts - game.totalTime
52 | game.totalTime = ts
53 | core.tick(game)
54 | w.swapBuffers()
55 | glfwPollEvents()
56 |
57 | w.destroyWindow()
58 | glfwTerminate()
59 |
--------------------------------------------------------------------------------
/vim3.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/oakes/vim_cubed/ea33fc71ae8d27351978e7e37057e69e3eb629e3/vim3.gif
--------------------------------------------------------------------------------
/vim3.nimble:
--------------------------------------------------------------------------------
1 | # Package
2 |
3 | version = "0.1.0"
4 | author = "oakes"
5 | description = "Vim for masochists"
6 | license = "Public Domain"
7 | srcDir = "src"
8 | bin = @["vim3"]
9 |
10 | task dev, "Run dev version":
11 | exec "nimble run vim3"
12 |
13 | # Dependencies
14 |
15 | requires "nim >= 1.2.6"
16 | requires "paranim >= 0.10.0"
17 | requires "paravim >= 0.18.2"
18 | requires "stb_image >= 2.5"
19 |
--------------------------------------------------------------------------------