From 94c2e4b46848a6cc84180d2a34b421920580e0ff Mon Sep 17 00:00:00 2001 From: Jakob Stasilowicz Date: Sat, 11 May 2019 16:46:57 +0200 Subject: [PATCH] Add code editor for scene. Add dynamic scene parser and transpiler. Add loader. Add PoC moveable camera --- index.html | 105 ++++- package-lock.json | 367 ++++++++++-------- package.json | 9 +- src/assets/models/octahedron.obj | 19 - src/assets/primitives/diamond.obj | 33 +- src/camera/index.js | 197 +++++++--- src/dtos/dynamic-scene/index.js | 107 +++++ src/index.js | 7 +- src/models/diamond/index.js | 17 + src/raytracer/index.js | 30 +- src/scenes/basic-scene/index.js.rtr | 56 +++ src/scenes/dyn-eval-test-scene/index.js | 124 ------ src/scenes/example-scene/index.js.rtr | 287 ++++++++++++++ .../generative-aniso-fog-test/index.js | 0 .../generative-iso-fog-test/index.js | 0 .../{ => legacy}/generative-test2/index.js | 0 src/store/index.js | 135 +++++-- src/styles/index.scss | 12 - .../controls/editor-controls/index.js | 27 ++ .../controls/editor-controls/index.scss | 15 + .../{ => controls}/render-controls/index.js | 19 +- .../{ => controls}/render-controls/index.scss | 0 .../{ => controls}/render-status/index.js | 2 +- .../{ => controls}/render-status/index.scss | 0 .../{ => controls}/save-controls/index.js | 6 +- .../{ => controls}/save-controls/index.scss | 2 +- .../{ => controls}/scene-controls/index.js | 4 +- .../{ => controls}/scene-controls/index.scss | 0 src/ui/components/editor/index.js | 68 ++++ src/ui/components/editor/index.scss | 28 ++ src/ui/components/progress-bar/index.scss | 4 +- src/ui/index.js | 38 +- src/ui/layout/index.scss | 3 +- src/utils/index.js | 4 + webpack.dev.js | 3 + webpack.prod.js | 3 + 36 files changed, 1268 insertions(+), 463 deletions(-) delete mode 100644 src/assets/models/octahedron.obj create mode 100644 src/dtos/dynamic-scene/index.js create mode 100644 src/models/diamond/index.js create mode 100644 src/scenes/basic-scene/index.js.rtr delete mode 100644 src/scenes/dyn-eval-test-scene/index.js create mode 100644 src/scenes/example-scene/index.js.rtr rename src/scenes/{ => legacy}/generative-aniso-fog-test/index.js (100%) rename src/scenes/{ => legacy}/generative-iso-fog-test/index.js (100%) rename src/scenes/{ => legacy}/generative-test2/index.js (100%) create mode 100644 src/ui/components/controls/editor-controls/index.js create mode 100644 src/ui/components/controls/editor-controls/index.scss rename src/ui/components/{ => controls}/render-controls/index.js (72%) rename src/ui/components/{ => controls}/render-controls/index.scss (100%) rename src/ui/components/{ => controls}/render-status/index.js (92%) rename src/ui/components/{ => controls}/render-status/index.scss (100%) rename src/ui/components/{ => controls}/save-controls/index.js (82%) rename src/ui/components/{ => controls}/save-controls/index.scss (90%) rename src/ui/components/{ => controls}/scene-controls/index.js (85%) rename src/ui/components/{ => controls}/scene-controls/index.scss (100%) create mode 100644 src/ui/components/editor/index.js create mode 100644 src/ui/components/editor/index.scss diff --git a/index.html b/index.html index ae20e20..230db92 100644 --- a/index.html +++ b/index.html @@ -3,10 +3,113 @@ + retrace.gl
- retrace.gl v.0.0.1-alpha +
+
+
+ retrace.gl v.0.0.1-alpha diff --git a/package-lock.json b/package-lock.json index 5919f01..1badcc7 100644 --- a/package-lock.json +++ b/package-lock.json @@ -416,6 +416,16 @@ "@babel/plugin-syntax-optional-catch-binding": "^7.2.0" } }, + "@babel/plugin-proposal-pipeline-operator": { + "version": "7.3.2", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-pipeline-operator/-/plugin-proposal-pipeline-operator-7.3.2.tgz", + "integrity": "sha512-wuzx8U/KZLJYoqU6joiaKY0PixHuYZ3Vxys+wPahNAZEEm+EDb1eTc19DuJob3BdxYSD9PWPbwyoRbhkdoYErg==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0", + "@babel/plugin-syntax-pipeline-operator": "^7.3.0" + } + }, "@babel/plugin-proposal-unicode-property-regex": { "version": "7.4.4", "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.4.4.tgz", @@ -425,49 +435,6 @@ "@babel/helper-plugin-utils": "^7.0.0", "@babel/helper-regex": "^7.4.4", "regexpu-core": "^4.5.4" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - }, - "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", - "dev": true - }, - "regexpu-core": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", - "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.0.2", - "regjsgen": "^0.5.0", - "regjsparser": "^0.6.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.1.0" - } - }, - "regjsgen": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", - "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==", - "dev": true - }, - "regjsparser": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", - "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - } - } } }, "@babel/plugin-syntax-async-generators": { @@ -524,6 +491,15 @@ "@babel/helper-plugin-utils": "^7.0.0" } }, + "@babel/plugin-syntax-pipeline-operator": { + "version": "7.3.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-pipeline-operator/-/plugin-syntax-pipeline-operator-7.3.0.tgz", + "integrity": "sha512-LAa3ZcOAyfPOUDTp0W5EiXGSAFh1vz9sD8yY7sZzWzEkZdIC404pqBP60Yfu9GJDj0ggh+UTQY6EYlIDXVr0/Q==", + "dev": true, + "requires": { + "@babel/helper-plugin-utils": "^7.0.0" + } + }, "@babel/plugin-transform-arrow-functions": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.2.0.tgz", @@ -577,14 +553,6 @@ "@babel/helper-replace-supers": "^7.4.4", "@babel/helper-split-export-declaration": "^7.4.4", "globals": "^11.1.0" - }, - "dependencies": { - "globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", - "dev": true - } } }, "@babel/plugin-transform-computed-properties": { @@ -614,49 +582,6 @@ "@babel/helper-plugin-utils": "^7.0.0", "@babel/helper-regex": "^7.4.4", "regexpu-core": "^4.5.4" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - }, - "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", - "dev": true - }, - "regexpu-core": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", - "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.0.2", - "regjsgen": "^0.5.0", - "regjsparser": "^0.6.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.1.0" - } - }, - "regjsgen": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", - "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==", - "dev": true - }, - "regjsparser": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", - "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - } - } } }, "@babel/plugin-transform-duplicate-keys": { @@ -851,17 +776,6 @@ "dev": true, "requires": { "regenerator-transform": "^0.13.4" - }, - "dependencies": { - "regenerator-transform": { - "version": "0.13.4", - "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.13.4.tgz", - "integrity": "sha512-T0QMBjK3J0MtxjPmdIMXm72Wvj2Abb0Bd4HADdfijwMdoIsyQZ6fWC7kDFhk2YinBBEMZDL7Y7wh0J1sGx3S4A==", - "dev": true, - "requires": { - "private": "^0.1.6" - } - } } }, "@babel/plugin-transform-reserved-words": { @@ -929,49 +843,6 @@ "@babel/helper-plugin-utils": "^7.0.0", "@babel/helper-regex": "^7.4.4", "regexpu-core": "^4.5.4" - }, - "dependencies": { - "jsesc": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", - "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", - "dev": true - }, - "regenerate": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", - "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", - "dev": true - }, - "regexpu-core": { - "version": "4.5.4", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", - "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", - "dev": true, - "requires": { - "regenerate": "^1.4.0", - "regenerate-unicode-properties": "^8.0.2", - "regjsgen": "^0.5.0", - "regjsparser": "^0.6.0", - "unicode-match-property-ecmascript": "^1.0.4", - "unicode-match-property-value-ecmascript": "^1.1.0" - } - }, - "regjsgen": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", - "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==", - "dev": true - }, - "regjsparser": { - "version": "0.6.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", - "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", - "dev": true, - "requires": { - "jsesc": "~0.5.0" - } - } } }, "@babel/polyfill": { @@ -1065,12 +936,6 @@ "node-releases": "^1.1.17" } }, - "caniuse-lite": { - "version": "1.0.30000966", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000966.tgz", - "integrity": "sha512-qqLQ/uYrpZmFhPY96VuBkMEo8NhVFBZ9y/Bh+KnvGzGJ5I8hvpIaWlF2pw5gqe4PLAL+ZjsPgMOvoXSpX21Keg==", - "dev": true - }, "electron-to-chromium": { "version": "1.3.131", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.131.tgz", @@ -1078,9 +943,9 @@ "dev": true }, "node-releases": { - "version": "1.1.17", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.17.tgz", - "integrity": "sha512-/SCjetyta1m7YXLgtACZGDYJdCSIBAWorDWkGCGZlydP2Ll7J48l7j/JxNYZ+xsgSPbWfdulVS/aY+GdjUsQ7Q==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.18.tgz", + "integrity": "sha512-/mnVgm6u/8OwlIsoyRXtTI0RfQcxZoAZbdwyXap0EeWwcOpDDymyCHM2/aR9XKmHXrvizHoPAOs0pcbiJ6RUaA==", "dev": true, "requires": { "semver": "^5.3.0" @@ -2141,6 +2006,12 @@ "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", "dev": true }, + "brace": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/brace/-/brace-0.11.1.tgz", + "integrity": "sha1-SJb8ydVE7vRfS7dmDbMg07N5/lg=", + "dev": true + }, "brace-expansion": { "version": "1.1.8", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.8.tgz", @@ -2442,6 +2313,12 @@ "integrity": "sha1-AHWP991fcTjTShVgjcz3Glllb/4=", "dev": true }, + "caniuse-lite": { + "version": "1.0.30000967", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000967.tgz", + "integrity": "sha512-rUBIbap+VJfxTzrM4akJ00lkvVb5/n5v3EGXfWzSH5zT8aJmGzjA8HWhJ4U6kCpzxozUSnB+yvAYDRPY6mRpgQ==", + "dev": true + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", @@ -2948,6 +2825,12 @@ } } }, + "core-js": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.0.1.tgz", + "integrity": "sha512-sco40rF+2KlE0ROMvydjkrVMMG1vYilP2ALoRXcYR4obqbYIuV3Bg+51GEDW+HF8n7NRA+iaA4qD0nD9lo9mew==", + "dev": true + }, "core-js-compat": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.0.1.tgz", @@ -2971,18 +2854,6 @@ "node-releases": "^1.1.17" } }, - "caniuse-lite": { - "version": "1.0.30000966", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30000966.tgz", - "integrity": "sha512-qqLQ/uYrpZmFhPY96VuBkMEo8NhVFBZ9y/Bh+KnvGzGJ5I8hvpIaWlF2pw5gqe4PLAL+ZjsPgMOvoXSpX21Keg==", - "dev": true - }, - "core-js": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.0.1.tgz", - "integrity": "sha512-sco40rF+2KlE0ROMvydjkrVMMG1vYilP2ALoRXcYR4obqbYIuV3Bg+51GEDW+HF8n7NRA+iaA4qD0nD9lo9mew==", - "dev": true - }, "electron-to-chromium": { "version": "1.3.131", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.131.tgz", @@ -2990,9 +2861,9 @@ "dev": true }, "node-releases": { - "version": "1.1.17", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.17.tgz", - "integrity": "sha512-/SCjetyta1m7YXLgtACZGDYJdCSIBAWorDWkGCGZlydP2Ll7J48l7j/JxNYZ+xsgSPbWfdulVS/aY+GdjUsQ7Q==", + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.18.tgz", + "integrity": "sha512-/mnVgm6u/8OwlIsoyRXtTI0RfQcxZoAZbdwyXap0EeWwcOpDDymyCHM2/aR9XKmHXrvizHoPAOs0pcbiJ6RUaA==", "dev": true, "requires": { "semver": "^5.3.0" @@ -3520,6 +3391,12 @@ "integrity": "sha512-ZIzRpLJrOj7jjP2miAtgqIfmzbxa4ZOr5jJc601zklsfEx9oTzmmj2nVpIPRpNlRTIh8lc1kyViIY7BWSGNmKw==", "dev": true }, + "diff-match-patch": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/diff-match-patch/-/diff-match-patch-1.0.4.tgz", + "integrity": "sha512-Uv3SW8bmH9nAtHKaKSanOQmj2DnlH65fUpcrMdfdaOxUG02QQ4YGZ8AE7kKOMisF7UqvOlGKVYWRvezdncW9lg==", + "dev": true + }, "diffie-hellman": { "version": "5.0.3", "resolved": "http://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz", @@ -5373,18 +5250,41 @@ "assert-plus": "^1.0.0" } }, + "gl-mat3": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gl-mat3/-/gl-mat3-1.0.0.tgz", + "integrity": "sha1-iWMyGcpCk3mha5GF2V1BcTRTuRI=", + "dev": true + }, "gl-matrix": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.0.0.tgz", "integrity": "sha512-PD4mVH/C/Zs64kOozeFnKY8ybhgwxXXQYGWdB4h68krAHknWJgk9uKOn6z8YElh5//vs++90pb6csrTIDWnexA==", "dev": true }, + "gl-quat": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gl-quat/-/gl-quat-1.0.0.tgz", + "integrity": "sha1-CUXskjOG9FMpvl3DV7HIwtR1hsU=", + "dev": true, + "requires": { + "gl-mat3": "^1.0.0", + "gl-vec3": "^1.0.3", + "gl-vec4": "^1.0.0" + } + }, "gl-vec3": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/gl-vec3/-/gl-vec3-1.1.3.tgz", "integrity": "sha512-jduKUqT0SGH02l8Yl+mV1yVsDfYgQAJyXGxkJQGyxPLHRiW25DwVIRPt6uvhrEMHftJfqhqKthRcyZqNEl9Xdw==", "dev": true }, + "gl-vec4": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gl-vec4/-/gl-vec4-1.0.1.tgz", + "integrity": "sha1-l9loeCgbFLUyy84QF4Xf0cs0CWQ=", + "dev": true + }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", @@ -5454,6 +5354,12 @@ "which": "^1.2.14" } }, + "globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "dev": true + }, "globby": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", @@ -5896,6 +5802,12 @@ "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==", "dev": true }, + "hotkeys-js": { + "version": "3.6.8", + "resolved": "https://registry.npmjs.org/hotkeys-js/-/hotkeys-js-3.6.8.tgz", + "integrity": "sha512-gDyqmHdVSc8ifh8bXCtnvZLwYrAIYBme9nmadyQ7G/vi9JEqXyyBUm809N4gwKJMWWxsxniM5OuvVuxGfmiFxw==", + "dev": true + }, "hpack.js": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", @@ -6781,6 +6693,12 @@ "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=", "dev": true }, + "jsesc": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz", + "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0=", + "dev": true + }, "json-parse-better-errors": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz", @@ -6850,6 +6768,12 @@ "integrity": "sha1-edk9LTM2PW/dKXCzNdkUGtWR15s=", "dev": true }, + "keycode": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/keycode/-/keycode-2.2.0.tgz", + "integrity": "sha1-PQr1bce4uOXLqNCpfxByBO7CKwQ=", + "dev": true + }, "killable": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz", @@ -7005,6 +6929,18 @@ "integrity": "sha1-4j8/nE+Pvd6HJSnBBxhXoIblzO8=", "dev": true }, + "lodash.get": { + "version": "4.4.2", + "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", + "integrity": "sha1-LRd/ZS+jHpObRDjVNBSZ36OCXpk=", + "dev": true + }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", + "dev": true + }, "lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", @@ -7466,6 +7402,15 @@ "integrity": "sha512-bV7f+6l2QigeBBZSM/6yTNq4P2fNpSWj/0e7jQcy87A8e7o2nAfP/34/2ky5Vw4B9S446EtIhodAzkFCcR4dQg==", "dev": true }, + "mouse-position": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mouse-position/-/mouse-position-2.1.0.tgz", + "integrity": "sha512-Ra8/RFn9e9/D2v9syhF5bLo4yiWvqZzcC/5bHOvkixDAkvO3WhlWN2xQRHSirMoYk2bagIae2upXXwxTxzI3BQ==", + "dev": true, + "requires": { + "events": "^1.0.1" + } + }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -9325,6 +9270,19 @@ "scheduler": "^0.13.6" } }, + "react-ace": { + "version": "6.5.0", + "resolved": "https://registry.npmjs.org/react-ace/-/react-ace-6.5.0.tgz", + "integrity": "sha512-W8iA6669Tf3sfjCsBg8gKs2pUVMy6BroX6O6GZcgadnLN+MTq7jhs6Q2Rsjq3E3SrWjyA9vZgs1Uzjy8XgWX5w==", + "dev": true, + "requires": { + "brace": "^0.11.1", + "diff-match-patch": "^1.0.4", + "lodash.get": "^4.4.2", + "lodash.isequal": "^4.5.0", + "prop-types": "^15.6.2" + } + }, "react-dom": { "version": "16.8.6", "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-16.8.6.tgz", @@ -9337,6 +9295,15 @@ "scheduler": "^0.13.6" } }, + "react-hot-keys": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/react-hot-keys/-/react-hot-keys-1.3.1.tgz", + "integrity": "sha512-Ino7daWt2lhUBo7Wr3ATr8dVrc1yyp9uPgR87lHrgV9poYDjh0y7BA3ClvkokcIyFoKIEcs3RQMHxuIAcjuQNg==", + "dev": true, + "requires": { + "hotkeys-js": "^3.6.2" + } + }, "react-is": { "version": "16.8.6", "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.8.6.tgz", @@ -9519,6 +9486,15 @@ } } }, + "regenerator-transform": { + "version": "0.13.4", + "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.13.4.tgz", + "integrity": "sha512-T0QMBjK3J0MtxjPmdIMXm72Wvj2Abb0Bd4HADdfijwMdoIsyQZ6fWC7kDFhk2YinBBEMZDL7Y7wh0J1sGx3S4A==", + "dev": true, + "requires": { + "private": "^0.1.6" + } + }, "regex-not": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz", @@ -9535,6 +9511,43 @@ "integrity": "sha512-LFrA98Dw/heXqDojz7qKFdygZmFoiVlvE1Zp7Cq2cvF+ZA+03Gmhy0k0PQlsC1jvHPiTUSs+pDHEuSWv6+6D7w==", "dev": true }, + "regexpu-core": { + "version": "4.5.4", + "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.5.4.tgz", + "integrity": "sha512-BtizvGtFQKGPUcTy56o3nk1bGRp4SZOTYrDtGNlqCQufptV5IkkLN6Emw+yunAJjzf+C9FQFtvq7IoA3+oMYHQ==", + "dev": true, + "requires": { + "regenerate": "^1.4.0", + "regenerate-unicode-properties": "^8.0.2", + "regjsgen": "^0.5.0", + "regjsparser": "^0.6.0", + "unicode-match-property-ecmascript": "^1.0.4", + "unicode-match-property-value-ecmascript": "^1.1.0" + }, + "dependencies": { + "regenerate": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.0.tgz", + "integrity": "sha512-1G6jJVDWrt0rK99kBjvEtziZNCICAuvIPkSiUFIQxVP06RCVpq3dmDo2oi6ABpYaDYaTRr67BEhL8r1wgEZZKg==", + "dev": true + }, + "regjsgen": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.0.tgz", + "integrity": "sha512-RnIrLhrXCX5ow/E5/Mh2O4e/oa1/jW0eaBKTSy3LaCj+M3Bqvm97GWDp2yUtzIs4LEn65zR2yiYGFqb2ApnzDA==", + "dev": true + }, + "regjsparser": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.6.0.tgz", + "integrity": "sha512-RQ7YyokLiQBomUJuUG8iGVvkgOLxwyZM8k6d3q5SAXpg4r5TZJZigKFvC6PpD+qQ98bCDC5YelPeA3EucDoNeQ==", + "dev": true, + "requires": { + "jsesc": "~0.5.0" + } + } + } + }, "regjsgen": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.2.0.tgz", @@ -9802,6 +9815,16 @@ "inherits": "^2.0.1" } }, + "rotate-vector-about-axis": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/rotate-vector-about-axis/-/rotate-vector-about-axis-1.0.2.tgz", + "integrity": "sha1-mvPbaHOEh9GlOhR3ysnet8ZHe/s=", + "dev": true, + "requires": { + "gl-quat": "^1.0.0", + "gl-vec3": "^1.0.3" + } + }, "run-queue": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz", diff --git a/package.json b/package.json index e7b3697..25817f3 100644 --- a/package.json +++ b/package.json @@ -31,13 +31,15 @@ "@babel/plugin-proposal-class-properties": "^7.0.0", "@babel/plugin-proposal-decorators": "^7.0.0", "@babel/plugin-proposal-object-rest-spread": "^7.0.0", + "@babel/plugin-proposal-pipeline-operator": "^7.3.2", "@babel/polyfill": "^7.0.0", - "@babel/preset-env": "^7.0.0", + "@babel/preset-env": "^7.4.4", "@babel/preset-react": "^7.0.0", "@babel/standalone": "^7.4.4", "ajv": "^6.10.0", "autoprefixer": "^9.5.0", "babel-loader": "^8.0.0", + "brace": "^0.11.1", "class-names": "^1.0.0", "clean-webpack-plugin": "^0.1.19", "copy-webpack-plugin": "^4.6.0", @@ -54,9 +56,11 @@ "hex-rgb": "^3.0.0", "html-webpack-plugin": "^3.2.0", "http-server": "^0.11.1", + "keycode": "^2.2.0", "loaders.gl": "^0.3.5", "lodash.chunk": "^4.2.0", "mobx-react-lite": "^1.3.1", + "mouse-position": "^2.1.0", "node-sass": "^4.11.0", "normals": "^1.1.0", "obj-mtl-loader": "0.0.5", @@ -66,7 +70,10 @@ "query-string": "^6.4.2", "raw-loader": "^1.0.0", "react": "^16.8.6", + "react-ace": "^6.5.0", "react-dom": "^16.8.6", + "react-hot-keys": "^1.3.1", + "rotate-vector-about-axis": "^1.0.2", "sass-loader": "^6.0.7", "save-canvas-to-image": "^0.1.1", "source-map-loader": "^0.2.4", diff --git a/src/assets/models/octahedron.obj b/src/assets/models/octahedron.obj deleted file mode 100644 index 408966e..0000000 --- a/src/assets/models/octahedron.obj +++ /dev/null @@ -1,19 +0,0 @@ -# OBJ file created by ply_to_obj.c -# -g Object001 - -v 1 0 0 -v 0 -1 0 -v -1 0 0 -v 0 1 0 -v 0 0 1 -v 0 0 -1 - -f 2 1 5 -f 3 2 5 -f 4 3 5 -f 1 4 5 -f 1 2 6 -f 2 3 6 -f 3 4 6 -f 4 1 6 diff --git a/src/assets/primitives/diamond.obj b/src/assets/primitives/diamond.obj index 519f3ac..408966e 100644 --- a/src/assets/primitives/diamond.obj +++ b/src/assets/primitives/diamond.obj @@ -1,20 +1,19 @@ -# diamond.obj - +# OBJ file created by ply_to_obj.c +# g Object001 -v 0.000000E+00 0.000000E+00 78.0000 -v 45.0000 45.0000 0.000000E+00 -v 45.0000 -45.0000 0.000000E+00 -v -45.0000 -45.0000 0.000000E+00 -v -45.0000 45.0000 0.000000E+00 -v 0.000000E+00 0.000000E+00 -78.0000 +v 1 0 0 +v 0 -1 0 +v -1 0 0 +v 0 1 0 +v 0 0 1 +v 0 0 -1 -f 1 2 3 -f 1 3 4 -f 1 4 5 -f 1 5 2 -f 6 5 4 -f 6 4 3 -f 6 3 2 -f 6 2 1 -f 6 1 5 +f 2 1 5 +f 3 2 5 +f 4 3 5 +f 1 4 5 +f 1 2 6 +f 2 3 6 +f 3 4 6 +f 4 1 6 diff --git a/src/camera/index.js b/src/camera/index.js index e899a63..7e8f422 100644 --- a/src/camera/index.js +++ b/src/camera/index.js @@ -1,4 +1,9 @@ import {vec3} from 'gl-matrix'; +import rotateVectorAboutAxis from 'rotate-vector-about-axis'; + +import mousePosition from 'mouse-position'; +import keycode from 'keycode'; + import { degToRad, defined, @@ -11,29 +16,139 @@ import { // vfov - vertical field of view // aspect ratio -function Camera({ - lookFrom, - lookAt, - vUp, - vfov, - aspect, - aperture, - focusDistance -}) { - this.cameraUniformName = 'camera'; - - this.lookFrom = lookFrom; - this.lookAt = lookAt; - this.vUp = vUp; - this.vfov = vfov; - this.aspect = aspect; - this.aperture = aperture; - this.lensRadius = aperture/2; - this.focusDist = !defined(focusDistance) - ? vec3.length(vec3.sub(vec3.create(), this.lookFrom, this.lookAt)) - : focusDistance; - - this.createCamera = () => { +class Camera { + cameraUniformName = 'camera'; + + mouseDeltaX = 0; + mouseDeltaY = 0; + mouseDown = false; + + moveVelocity = 0.5; + turningVelocity = 0.0125; // 0.025 + + constructor({ + lookFrom, + lookAt, + vUp, + vfov, + aspect, + aperture, + focusDistance + }) { + this.lookFrom = lookFrom; + this.lookAt = lookAt; + this.vUp = vUp; + this.vfov = vfov; + this.aspect = aspect; + this.aperture = aperture; + this.lensRadius = aperture/2; + this.focusDist = focusDistance; + + this.updateCamera(); + this.listen(); + } + + // https://github.com/Erkaman/gl-movable-camera/blob/master/index.js + + listen = () => { + this.mouse = mousePosition(document.body); + + document.addEventListener('mousedown', (e) => { + this.mouseDown = true; + }); + + document.addEventListener('mouseup', (e) => { + this.mouseDown = false; + }); + + document.addEventListener('keydown', (e) => { + let moveDir = vec3.create(); + + switch(keycode(e)) { + // forward + case 'w': + vec3.scale(moveDir, this.w, -this.moveVelocity); + + vec3.add(this.lookFrom, this.lookFrom, moveDir); + vec3.add(this.lookAt, this.lookAt, moveDir); + + break; + + // back + case 's': + vec3.scale(moveDir, this.w, this.moveVelocity); + + vec3.add(this.lookFrom, this.lookFrom, moveDir); + vec3.add(this.lookAt, this.lookAt, moveDir); + + break; + + // left + case 'a': + vec3.scale(moveDir, this.u, -this.moveVelocity); + + vec3.add(this.lookFrom, this.lookFrom, moveDir); + vec3.add(this.lookAt, this.lookAt, moveDir); + + break; + + // right + case 'd': + vec3.scale(moveDir, this.u, this.moveVelocity); + + vec3.add(this.lookFrom, this.lookFrom, moveDir); + vec3.add(this.lookAt, this.lookAt, moveDir); + + break; + + case 'up': + vec3.scale(moveDir, this.v, this.moveVelocity); + + vec3.add(this.lookFrom, this.lookFrom, moveDir); + vec3.add(this.lookAt, this.lookAt, moveDir); + + break; + + case 'down': + vec3.scale(moveDir, this.v, -this.moveVelocity); + + vec3.add(this.lookFrom, this.lookFrom, moveDir); + vec3.add(this.lookAt, this.lookAt, moveDir); + + break; + + default: + break; + } + }); + } + + update = () => { + this.mouseDeltaX = -(this.mouse[0] - this.mouse.prev[0]); + this.mouseDeltaY = -(this.mouse[1] - this.mouse.prev[1]); + this.mouse.flush(); + + if(this.mouseDown) { + const turningVelocity = 0.025; + let [head, pitch] = [this.mouseDeltaX, this.mouseDeltaY]; + + // rotate about up vector. + this.lookFrom = rotateVectorAboutAxis(this.lookFrom, this.u, pitch * turningVelocity); + this.lookAt = rotateVectorAboutAxis(this.lookAt, this.u, pitch * turningVelocity); + + // rotate about right vector. + this.lookFrom = rotateVectorAboutAxis(this.lookFrom, this.v, head * turningVelocity); + this.lookAt = rotateVectorAboutAxis(this.lookAt, this.v, head * turningVelocity); + } + + this.updateCamera(); + } + + updateCamera = () => { + this.focusDist = !defined(this.focusDist) + ? vec3.length(vec3.sub(vec3.create(), this.lookFrom, this.lookAt)) + : this.focusDist; + let theta = degToRad(this.vfov); // vfov is top to bottom in degs let halfHeight = Math.tan(theta/2.); let halfWidth = this.aspect * halfHeight; @@ -42,47 +157,37 @@ function Camera({ * calc camera basis */ - // vec3 w = normalize(lookFrom - lookAt); + // vec3 w = normalize(this.lookFrom - this.lookAt); this.w = vec3.create(); - this.w = vec3.normalize(this.w, vec3.sub(vec3.create(), lookFrom, lookAt)); + vec3.sub(this.w, this.lookFrom, this.lookAt); + this.w = vec3.normalize(this.w, this.w); // vec3 u = normalize(cross(vUp, w)); this.u = vec3.create(); - vec3.normalize(this.u, vec3.cross(vec3.create(), this.vUp, this.w)); + vec3.cross(this.u, this.vUp, this.w); + vec3.normalize(this.u, this.u); // vec3 v = cross(w, u); - this.v = vec3.cross(vec3.create(), this.w, this.u); + this.v = vec3.create(); + vec3.cross(this.v, this.w, this.u); /* * adjust basis to aspect, focus distance and get starting pos (lowerLeft) */ - // vec3 lowerLeft = lookFrom - halfWidth*this.focusDist*u - halfHeight*this.focusDist*v - w*this.focusDist; this.lowerLeft = vec3.create(); vec3.sub(this.lowerLeft, this.lookFrom, vec3.scale(vec3.create(), this.u, halfWidth*this.focusDist)); vec3.sub(this.lowerLeft, this.lowerLeft, vec3.scale(vec3.create(), this.v, halfHeight*this.focusDist)); vec3.sub(this.lowerLeft, this.lowerLeft, vec3.scale(vec3.create(), this.w, this.focusDist)); - // vec3 horizontal = 2.*this.focusDist*halfWidth*u; - this.horizontal = vec3.scale(vec3.create(), this.u, 2*this.focusDist*halfWidth); + this.horizontal = vec3.create(); + vec3.scale(this.horizontal, this.u, 2*this.focusDist*halfWidth); - // vec3 vertical = 2.*this.focusDist*halfHeight*v; - this.vertical = vec3.scale(vec3.create(), this.v, 2*this.focusDist*halfHeight); + this.vertical = vec3.create(); + vec3.scale(this.vertical, this.v, 2*this.focusDist*halfHeight); } - this.getDefinition = () => ` - Camera( - vec3(${this.lookFrom}), - vec3(${this.horizontal}), - vec3(${this.vertical}), - vec3(${this.lowerLeft}), - ${this.lensRadius}, - // camera basis - vec3(${this.w}), vec3(${this.u}), vec3(${this.v}) - ); - `; - - this.getUniform = () => ({ + getUniform = () => ({ [`${this.cameraUniformName}.origin`]: this.lookFrom, [`${this.cameraUniformName}.horizontal`]: this.horizontal, [`${this.cameraUniformName}.vertical`]: this.vertical, @@ -93,9 +198,9 @@ function Camera({ [`${this.cameraUniformName}.v`]: this.v }); - this.createCamera(); } + function createCamera({lookFrom, lookAt, vUp, vfov, aperture, aspect}) { let lookFromVec = vec3.create(); lookFromVec.set(lookFrom); diff --git a/src/dtos/dynamic-scene/index.js b/src/dtos/dynamic-scene/index.js new file mode 100644 index 0000000..ad20cec --- /dev/null +++ b/src/dtos/dynamic-scene/index.js @@ -0,0 +1,107 @@ +import * as babel from '@babel/core'; + +import babelEnvPreset from '@babel/preset-env'; +import babelDecoratorPlugin from '@babel/plugin-proposal-decorators'; +import babelObjSpreadPlugin from '@babel/plugin-proposal-object-rest-spread'; +import babelPipesPlugin from '@babel/plugin-proposal-pipeline-operator'; + +import Scene from '../../dtos/scene'; + +import ObjModel from '../../models/obj-model'; +import Plane from '../../models/plane'; +import Cube from '../../models/cube'; +import Sphere from '../../models/sphere'; +import Diamond from '../../models/diamond'; + +import Texture from '../../texture'; + +import MetalMaterial from '../../materials/metal'; +import LambertMaterial from '../../materials/lambert'; +import EmissiveMaterial from '../../materials/emissive'; +import DialectricMaterial from '../../materials/dialectric'; + +import IsotropicVolumeMaterial from '../../materials/isotropic-volume'; +import AnisotropicVolumeMaterial from '../../materials/anisotropic-volume'; + +import { + random as _random, + randomIdx as _randomIdx, + randomBool as _randomBool, + maybe as _maybe, + pluckRandom as _pluckRandom, + takeRandom as _takeRandom, + range as _range, + range2d as _range2d, + subRange as _subRange, + glslFloat as _glslFloat, + normedColor as _normedColor, + normedColorStr as _normedColorStr, + degToRad as _degToRad +} from '../../utils'; + +// bring everything into local scope +// and add some syntactic sugar + +const random = _random; +const randomIdx = _randomIdx; +const randomBool = _randomBool; +const maybe = _maybe; +const pluckRandom = _pluckRandom; +const takeRandom = _takeRandom; +const range = _range; +const range2d = _range2d; +const subRange = _subRange; +const glslFloat = _glslFloat; +const normedColor = _normedColor; +const normedColorStr = _normedColorStr; +const degToRad = _degToRad; + +const scene = (s) => + new Scene(s); + +const objModel = (o) => + new ObjModel(o); +const plane = (o) => + new Plane(o); +const cube = (o) => + new Cube(o); +const sphere = (o) => + new Sphere(o); +const diamond = (o) => + new Diamond(o); + +const texture = (o) => + new Texture(o); + +const lambertMaterial = (o) => + new LambertMaterial(o); +const metalMaterial = (o) => + new MetalMaterial(o); +const dialectricMaterial = (o) => + new DialectricMaterial(o); +const emissiveMaterial = (o) => + new EmissiveMaterial(o); +const isotropicVolumeMaterial = (o) => + new IsotropicVolumeMaterial(o); +const anisotropicVolumeMaterial = (o) => + new AnisotropicVolumeMaterial(o); + +let cachedSrc = null; +let transpiledSrc = null; + +export default async (src) => { + if(cachedSrc != src) { + transpiledSrc = babel.transformSync(src, { + presets: [babelEnvPreset], + plugins: [ + [babelDecoratorPlugin, {legacy: true}], + babelObjSpreadPlugin, + [babelPipesPlugin, {proposal: 'smart'}] + ] + }); + + cachedSrc = src; + } + + return eval(transpiledSrc.code); +} diff --git a/src/index.js b/src/index.js index 083528f..27bb580 100644 --- a/src/index.js +++ b/src/index.js @@ -1,20 +1,17 @@ import React from 'react'; import ReactDOM from 'react-dom'; -import queryString from 'query-string'; - -import raytraceApp from './raytracer'; -import createScene from './scenes/generative-iso-fog-test'; +import UI from './ui'; import 'normalize.css/normalize.css'; import './styles/index.scss'; -import UI from './ui'; import getStore from './store'; document.addEventListener('DOMContentLoaded', async () => { const store = getStore(); await store.loadScene(); + store.finishLoad(); store.trace(); ReactDOM.render( diff --git a/src/models/diamond/index.js b/src/models/diamond/index.js new file mode 100644 index 0000000..0d5fe56 --- /dev/null +++ b/src/models/diamond/index.js @@ -0,0 +1,17 @@ +import ObjModel from '../obj-model'; + +class Diamond { + constructor(opts) { + // "await new Obj()" + return (async () => { + return new ObjModel({ + url: 'assets/primitives/diamond.obj', + smoothShading: false, + doubleSided: true, + ...opts + }); + })(); + } +} + +export default Diamond diff --git a/src/raytracer/index.js b/src/raytracer/index.js index 629915f..bcfcb97 100644 --- a/src/raytracer/index.js +++ b/src/raytracer/index.js @@ -8,7 +8,7 @@ import queryString from 'query-string'; import {getGlInstances} from '../gl'; import {createCamera} from '../camera'; -import createScene from '../scenes/generative-iso-fog-test'; +// import createScene from '../scenes/generative-iso-fog-test'; import vertShader from '../shaders/vert.glsl'; import rayTraceShader from '../shaders/raytracer.glsl.js'; @@ -55,12 +55,13 @@ async function raytraceApp({ // gl.pixelStorei(gl.UNPACK_ALIGNMENT, alignment); // for triangle scene - const camera = createCamera({ - lookFrom: [3.1, 1.2, 1.9], - lookAt: [-0.25, 0.1, -1.5], + let camera = createCamera({ + lookFrom: [3.1, 1.4, 1.9], + // lookAt: [-0.25, 0.1, -1.5], + lookAt: [-0.25, 0.75, -1.5], vUp: [0, 1, 0], - vfov: 40, //35, //25, - aperture: 0.015, + vfov: 45, //40, //35, //25, + aperture: 0.001, //0.015, aspect: glCanvas.width/glCanvas.height, }); @@ -219,7 +220,7 @@ async function raytraceApp({ // camera uniform // TODO: make this a uniform buffer - const cameraUniform = camera.getUniform(); + let cameraUniform = camera.getUniform(); Object.keys(cameraUniform) .forEach(uniformName => rayTraceDrawCall.uniform(uniformName, cameraUniform[uniformName]) @@ -300,6 +301,8 @@ async function raytraceApp({ /////////////////////////////////////////////////////////// }); + + return frame; } const realTimeRender = () => { @@ -312,6 +315,13 @@ async function raytraceApp({ stats.begin(); glApp.clear(); + camera.update(); + let cameraUniform = camera.getUniform(); + Object.keys(cameraUniform) + .forEach(uniformName => + rayTraceDrawCall.uniform(uniformName, cameraUniform[uniformName]) + ); + rayTraceDrawCall .uniform('uTime', time * 0.01) .uniform('uSeed', vec2.fromValues(random(), random())) @@ -319,12 +329,14 @@ async function raytraceApp({ stats.end(); }); + + return frame; } if(!realTime) { - staticRender(); + return staticRender(); } else { - realTimeRender(); + return realTimeRender(); } } diff --git a/src/scenes/basic-scene/index.js.rtr b/src/scenes/basic-scene/index.js.rtr new file mode 100644 index 0000000..17e3218 --- /dev/null +++ b/src/scenes/basic-scene/index.js.rtr @@ -0,0 +1,56 @@ +scene({ + geometries: [ + plane({ + material: 'lambert-white', + texture: 'check', + scale: 30, + position: { + x: 0.3, + y: 0.0, + z: -0.4 + }, + rotation: { + y: degToRad(60) + } + }), + sphere({ + material: 'ceil-light', + position: { + x: -4.5, + y: 15, + z: -7.5 + }, + radius: 10 + }) + ], + textures: [ + texture({ + name: 'check', + src: ` + float s = sin(500.*uv.x)*sin(500.*uv.y); + if(s < 0.) { + tColor = vec4(${normedColorStr('#ff0000')}, 1.0); + } else { + tColor = vec4(1., 1., 1., 1.); + } + ` + }), + ], + materials: [ + lambertMaterial({ + name: 'lambert-white', + color: '#ffffff', + albedo: [0.8, 0.8, 0.8] + }), + emissiveMaterial({ + name: 'white-light', + color: '#ffffff', + intensity: 30 + }), + emissiveMaterial({ + name: 'ceil-light', + color: '#ffffff', + intensity: 0.1 + }) + ] +}); diff --git a/src/scenes/dyn-eval-test-scene/index.js b/src/scenes/dyn-eval-test-scene/index.js deleted file mode 100644 index 8c1d3e9..0000000 --- a/src/scenes/dyn-eval-test-scene/index.js +++ /dev/null @@ -1,124 +0,0 @@ -import ObjModel from '../../models/obj-model'; -import Sphere from '../../models/sphere'; -import Plane from '../../models/plane'; -import Cube from '../../models/Cube'; - -import Scene from '../../dtos/scene'; - -import Texture from '../../texture'; - -import MetalMaterial from '../../materials/metal'; -import LambertMaterial from '../../materials/lambert'; -import EmissiveMaterial from '../../materials/emissive'; -import DialectricMaterial from '../../materials/dialectric'; - -import IsotropicVolumeMaterial from '../../materials/isotropic-volume'; -import AnisotropicVolumeMaterial from '../../materials/anisotropic-volume'; - -import * as babel from "@babel/core"; - -import { - random, - randomIdx, - randomBool, - maybe, - pluckRandom, - range, - range2d, - glslFloat, - flatten, - normedColor, - normedColorStr, - degToRad -} from '../../utils'; - -// console.log('kaka :D ') -// -// import _sphere from '!!raw-loader!./../../models/sphere'; -// import _sphere from '!!raw-loader!./../../models/sphere'; - -let scene = Scene; -const sphere = Sphere; -const plane = Plane; -const texture = Texture; -const emissiveMaterial = EmissiveMaterial; -const lambertMaterial = LambertMaterial; -const _degToRad = degToRad; -const _normedColorStr = normedColorStr; - -// var jsCode = babel.transform(` -// console.log('helo :)'); -// console.dir(sphere); -// new sphere({ material: 'volume' }) -// `); -// -// console.log(jsCode); -// -// console.dir(eval(jsCode.code)); -// eval(jsCode.code); - -const code = babel.transform(` - console.log('fasdfadf'); - - new scene({ - geometries: [ - new plane({ - material: 'lambert-white', - texture: 'check', - scale: 30, - position: { - x: 0.3, - y: 0.0, - z: -0.4 - }, - rotation: { - y: _degToRad(60) - } - }), - new sphere({ - material: 'ceil-light', - // texture: 'check', - position: { - x: -4.5, - y: 15, - z: -7.5 - }, - radius: 10 - }) - ], - textures: [ - new texture({ - name: 'check', - src: \` - float s = sin(500.*uv.x)*sin(500.*uv.y); - if(s < 0.) { - tColor = vec4(\${_normedColorStr('#ff0000')}, 1.0); - } else { - tColor = vec4(1., 1., 1., 1.); - } - \` - }), - ], - materials: [ - new lambertMaterial({ - name: 'lambert-white', - color: '#ffffff', - albedo: [0.8, 0.8, 0.8] - }), - new emissiveMaterial({ - name: 'white-light', - color: '#ffffff', - intensity: 30 - }), - new emissiveMaterial({ - name: 'ceil-light', - color: '#ffffff', - intensity: 0.1 //0.05 - }) - ] - }); -`); - -export default async () => { - return eval(code.code); -} diff --git a/src/scenes/example-scene/index.js.rtr b/src/scenes/example-scene/index.js.rtr new file mode 100644 index 0000000..c956641 --- /dev/null +++ b/src/scenes/example-scene/index.js.rtr @@ -0,0 +1,287 @@ +scene({ + geometries: [ + plane({ + material: 'floor-white', + texture: 'check', + scale: 30, + position: { + x: 0.3, + y: 0.0, + z: -0.4 + }, + rotation: { + y: degToRad(60) + } + }), + sphere({ + material: 'volume-red', + position: { + x: -1.5, + y: 0, + z: -2 + }, + radius: 4.4 + }), + sphere({ + material: 'ceil-light', + position: { + x: -4.5, + y: 36, + z: -7.5 + }, + radius: 30 + }), + diamond({ + material: 'box-light', + scale: 0.4,//0.8, + position: { + x: -0.3, + y: 1.0, + z: -1.6 + }, + rotation: { + y: degToRad(220), + // x: degToRad(-45), + } + }), + diamond({ + material: 'box-glass', + scale: 0.81,//0.8, + position: { + x: -0.3, + y: 1.0, + z: -1.6 + }, + rotation: { + y: degToRad(220), + // x: degToRad(-45), + } + }), + // objModel({ + // url: 'assets/models/hand.obj', + // material: 'hand-fuzzy-metal', + // smoothShading: true, + // scale: 0.05, + // position: { + // x: 0.8, + // y: 0.8, + // z: -1.4 + // }, + // rotation: { + // y: degToRad(-10), + // x: degToRad(-45), + // } + // }), + range2d(0, 15, 0, 15) + |> subRange(#, range2d(2, 6, 2, 6)) + |> takeRandom + |> #.map(([x, z]) => { + const glassCube = ({ + scale, + material, + texture, + glassDistance, + ...props + }) => [ + cube({ + scale, + material, + texture, + ...props + }), + cube({ + scale: { + x: scale.x + glassDistance, + y: scale.y + glassDistance, + z: scale.z + glassDistance + }, + material: 'box-glass', + ...props + }) + ]; + + const material = pluckRandom([ + 'box-black', + 'box-white', + 'box-light', + 'box-glass' + ]); + + const scale = 0.5; + + const props = { + material, + scale: { + x: scale, + y: scale + + (x + 1) * (z + 1) * 0.1, + z: scale, + }, + position: { + x: 1.2 - x*(scale+0.15), + y: 0.1, + z: 0.1 - z*(scale+0.15) + }, + }; + + return material !== 'box-black' + && material !== 'box-white' + ? new glassCube({ + ...props, + texture: `pattern-${randomIdx(6)}`, + glassDistance: 0.05, + }) + : material === 'box-black' + ? [ + cube(props), + sphere({ + position: { + x: props.position.x, + y: props.position.y + props.scale.y/2, + z: props.position.z, + }, + material: 'halfsphere-light', + radius: 0.1 + }) + ] + : [cube(props)]; + }), + ], + textures: [ + texture({ + name: 'check', + src: ` + float s = sin(500.*uv.x)*sin(500.*uv.y); + if(s < 0.) { + tColor = vec4(${normedColorStr('#aaaaaa')}, 1.0); + } else { + tColor = vec4(0.05, 0.05, 0.05, 1.); + } + ` + }), + ...range(0, 6).map(i => + texture({ + name: `pattern-${i}`, + src: ` + vec2 rotate2D (vec2 _st, float _angle) { + _st -= 0.5; + _st = mat2(cos(_angle),-sin(_angle), + sin(_angle),cos(_angle)) * _st; + _st += 0.5; + return _st; + } + + vec2 tile (vec2 _st, float _zoom) { + _st *= _zoom; + return fract(_st); + } + + vec2 rotateTilePattern(vec2 _st) { + // Scale the coordinate system by 2x2 + _st *= 0.5 + ${glslFloat(random(2))}; + + // Give each cell an index number + // according to its position + float index = 0.0; + index += step(1., mod(_st.x,2.0)); + index += step(1., mod(_st.y,2.0))*2.0; + + // Make each cell between 0.0 - 1.0 + _st = fract(_st); + + // Rotate each cell according to the index + if(index == 1.0){ + // Rotate cell 1 by 90 degrees + _st = rotate2D(_st,PI*0.5); + } else if(index == 2.0){ + // Rotate cell 2 by -90 degrees + _st = rotate2D(_st,PI*-0.5); + } else if(index == 3.0){ + // Rotate cell 3 by 180 degrees + _st = rotate2D(_st,PI); + } + + return _st; + } + + void renderTexture(vec2 uv, out vec4 tColor) { + vec2 st = uv; + + st = tile(st, 3.0); + st = rotateTilePattern(st); + + // Make more interesting combinations + + ${randomBool() + ? 'st = tile(st,2.0);' + : '' + } + + ${randomBool() + ? `st = rotate2D(st,-PI * ${glslFloat(random(3))} * 0.25);` + : '' + } + + // st = rotateTilePattern(st*2.); + // st = rotate2D(st,PI*u_time*0.25); + + // step(st.x,st.y) just makes a b&w triangles + // but you can use whatever design you want. + tColor = vec4(vec3(step(st.x,st.y))*0.5, 1.0); + } + ` + }) + ) + ], + materials: [ + anisotropicVolumeMaterial({ + name: 'volume-red', + color: '#ff0000', + albedo: [1.0, 1.0, 1.0], + density: 1.15, + volumeScale: 7 + }), + dialectricMaterial({ + name: 'box-glass' + }), + metalMaterial({ + name: `box-black`, + color: '#030303', + fuzz: 0.2, + albedo: [0.9, 0.9, 0.9] + }), + metalMaterial({ + name: `box-white`, + color: '#ffffff', + fuzz: 0.2, + albedo: [0.9, 0.9, 0.9] + }), + metalMaterial({ + name: `floor-white`, + color: '#ffffff', + fuzz: 0.15, + albedo: [0.8, 0.8, 0.8] + }), + metalMaterial({ + name: 'hand-fuzzy-metal', + color: '#ffffff', + fuzz: 0.05, + albedo: [0.9, 0.9, 0.9] + }), + emissiveMaterial({ + name: `halfsphere-light`, + color: '#ffffff', + intensity: 30 + }), + emissiveMaterial({ + name: `ceil-light`, + color: '#ffffff', + intensity: 0.05 + }), + emissiveMaterial({ + name: `box-light`, + color: '#ffffff', + intensity: 10 + }) + ] +}); diff --git a/src/scenes/generative-aniso-fog-test/index.js b/src/scenes/legacy/generative-aniso-fog-test/index.js similarity index 100% rename from src/scenes/generative-aniso-fog-test/index.js rename to src/scenes/legacy/generative-aniso-fog-test/index.js diff --git a/src/scenes/generative-iso-fog-test/index.js b/src/scenes/legacy/generative-iso-fog-test/index.js similarity index 100% rename from src/scenes/generative-iso-fog-test/index.js rename to src/scenes/legacy/generative-iso-fog-test/index.js diff --git a/src/scenes/generative-test2/index.js b/src/scenes/legacy/generative-test2/index.js similarity index 100% rename from src/scenes/generative-test2/index.js rename to src/scenes/legacy/generative-test2/index.js diff --git a/src/store/index.js b/src/store/index.js index daf2255..992a510 100644 --- a/src/store/index.js +++ b/src/store/index.js @@ -3,48 +3,119 @@ import { observable, computed, - action + action, } from 'mobx'; import raytraceApp from '../raytracer'; -import createIsoFogScene from '../scenes/generative-iso-fog-test'; -import createAnisoFogScene from '../scenes/generative-aniso-fog-test'; -import createDynEvalScene from '../scenes/dyn-eval-test-scene'; +// import createIsoFogScene from '../scenes/generative-iso-fog-test'; +// import createAnisoFogScene from '../scenes/generative-aniso-fog-test'; +// import createDynEvalScene from '../scenes/dyn-eval-test-scene'; + +import dynamicScene from '../dtos/dynamic-scene'; + +import introSceneSrc from '../scenes/example-scene/index.js.rtr'; +import basicSceneSrc from '../scenes/basic-scene/index.js.rtr'; const shaderSampleCount = 1; const defaultMaxSampleCount = 10; let instance = null; class Store { + @observable _loadingApp = true; + @observable _renderInProgress = false; + @observable _editorVisible = false; + + @observable _sceneSrc = introSceneSrc; + @observable _scene = null; + @observable _currentFrameCount = 0; @observable _currentMaxSampleCount = defaultMaxSampleCount; @observable _currentRenderTime = 0; - @observable _renderInProgress = false; - @observable _scene = null; + _activeRenderInstance = null; constructor() { - // let params = queryString.parse(location.search);; - // this.params = params; + // } - @action async loadScene() { - // this._scene = await createAnisoFogScene(); - this._scene = await createDynEvalScene(); + // actions + + @action + async loadScene() { + this._scene = await dynamicScene(this._sceneSrc); } - trace() { - raytraceApp({ + @action async regenerateScene() { + await this.loadScene(); + this.currentMaxSampleCount = defaultMaxSampleCount; + this.trace(); + } + + @action + async trace() { + // this._activeRenderInstance = await raytraceApp({ + // scene: this._scene, + // shaderSampleCount, + // maxSampleCount: this._currentMaxSampleCount, + // realTime: false, + // debug: false + // }); + + this._activeRenderInstance = await raytraceApp({ scene: this._scene, - shaderSampleCount, + shaderSampleCount: 1, //shaderSampleCount, maxSampleCount: this._currentMaxSampleCount, - realTime: false, + realTime: true, debug: false }); + + } + + @action + cancelTrace() { + if(this._activeRenderInstance) { + this._activeRenderInstance.cancel(); + delete this._activeRenderInstance; + this.renderInProgress = false; + } + } + + @action + handleUiKeyShortcut = (keyName, e, handle) => { + switch(keyName) { + case 'alt+r': + this.trace(); + break; + + case 'alt+g': + this.regenerateScene(); + break; + + case 'alt+h': + this.editorVisible = !this.editorVisible; + break; + + default: + break; + } + } + + // main state + + @computed + get loadingApp() { + return this._loadingApp; } - // renderer state + finishLoad() { + let loader = document.querySelector('.loader'); + loader.remove(); + + // loader.style.display = 'none'; + + this._loadingApp = false; + } @computed get renderInProgress() { @@ -55,6 +126,26 @@ class Store { this._renderInProgress = val; } + @computed + get editorVisible() { + return this._editorVisible; + } + + set editorVisible(val) { + this._editorVisible = val; + } + + @computed + get sceneSrc() { + return this._sceneSrc; + } + + set sceneSrc(val) { + this._sceneSrc = val; + } + + // stats + @computed get currentFrameCount() { return this._currentFrameCount; @@ -84,23 +175,15 @@ class Store { @computed get renderTimeRemaining() { - const remainMs = (this.currentMaxSampleCount / this._currentFrameCount) + const remainSecs = (this.currentMaxSampleCount / this._currentFrameCount) * this.currentRenderTime; - return (remainMs).toFixed(0); + return (remainSecs).toFixed(0); } @computed get renderProgress() { return this._currentFrameCount / this._currentMaxSampleCount; } - - // actions - - @action async regenerateScene() { - await this.loadScene(); - this.currentMaxSampleCount = defaultMaxSampleCount; - this.trace(); - } } export default () => { diff --git a/src/styles/index.scss b/src/styles/index.scss index 980ae05..66114be 100644 --- a/src/styles/index.scss +++ b/src/styles/index.scss @@ -20,18 +20,6 @@ body { font-weight: lighter; } -#plug { - position: absolute; - bottom: 15px; - right: 15px; - - z-index: 2; - - color: white; - font-size: 12px; - opacity: 0.5; -} - canvas#gl-canvas { position: absolute; diff --git a/src/ui/components/controls/editor-controls/index.js b/src/ui/components/controls/editor-controls/index.js new file mode 100644 index 0000000..e1590d3 --- /dev/null +++ b/src/ui/components/controls/editor-controls/index.js @@ -0,0 +1,27 @@ +import React from 'react'; +import ReactDOM from 'react-dom'; +import {observer} from 'mobx-react-lite'; +import saveCanvas from "save-canvas-to-image"; + +import getStore from '../../../../store'; + +import './index.scss'; + +const EditorControls = observer(() => { + const store = getStore(); + + return ( +
+ +
+ ) +}); + +export default EditorControls; diff --git a/src/ui/components/controls/editor-controls/index.scss b/src/ui/components/controls/editor-controls/index.scss new file mode 100644 index 0000000..591adde --- /dev/null +++ b/src/ui/components/controls/editor-controls/index.scss @@ -0,0 +1,15 @@ +.edit-controls { + button { + background: transparent; + margin-left: 5px; + color: white; + text-decoration: underline; + border: none; + cursor: pointer; + + &:disabled { + opacity: 0.5; + cursor: not-allowed; + } + } +} diff --git a/src/ui/components/render-controls/index.js b/src/ui/components/controls/render-controls/index.js similarity index 72% rename from src/ui/components/render-controls/index.js rename to src/ui/components/controls/render-controls/index.js index 8fe9f22..0aac67e 100644 --- a/src/ui/components/render-controls/index.js +++ b/src/ui/components/controls/render-controls/index.js @@ -4,7 +4,7 @@ import ReactDOM from 'react-dom'; import {reaction} from 'mobx'; import {observer, useObservable} from 'mobx-react-lite'; -import getStore from '../../../store'; +import getStore from '../../../../store'; import './index.scss'; @@ -28,8 +28,12 @@ const RenderControls = observer(() => {
{ e.preventDefault(); - store.currentMaxSampleCount = state.maxSampleCount; - store.trace(); + if(store.renderInProgress) { + store.cancelTrace(); + } else { + store.currentMaxSampleCount = state.maxSampleCount; + store.trace(); + } }} >