feat: Add legacy shaders, model I/O, and project panel functionality
continuous-integration/drone/push Build is passing
- Introduced `legacy-shaders.js` containing vertex and fragment shaders for rendering. - Implemented `model-io.js` for parsing and encoding GLB files, ensuring compatibility with glTF 2.0. - Created `project-panel.js` to manage project resources and survey overlays, enhancing user interaction. - Added `solar.js` for calculating solar positions based on UTC time, latitude, and longitude. - Developed `three-renderer.js` as a standard backend for Three.js, managing scene rendering and material synchronization. - Included a new GLB model `dum.glb` for testing and demonstration purposes. - Established `data_checks.mjs` for validating model data and ensuring integrity of assets. - Created `prepare_export.py` to facilitate Blender GLB exports, maintaining material and node references. - Added `vendor_three.py` to download and configure a local version of Three.js for the project.
@@ -1,10 +1,3 @@
|
|||||||
<?php
|
<?php
|
||||||
// Upload this whole folder, not only this file. No Node.js or database required.
|
|
||||||
header('Content-Type: text/html; charset=utf-8');
|
readfile(__DIR__ . '/dum_3D_slunce.html');
|
||||||
header('X-Content-Type-Options: nosniff');
|
|
||||||
$file = __DIR__ . '/app.html';
|
|
||||||
if (!is_readable($file)) {
|
|
||||||
http_response_code(500);
|
|
||||||
exit('Chybi app.html. Nahrajte celou slozku locenice.');
|
|
||||||
}
|
|
||||||
readfile($file);
|
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 2.1 KiB After Width: | Height: | Size: 2.1 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 3.6 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 2.9 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 1.8 KiB After Width: | Height: | Size: 1.8 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 2.4 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 3.2 KiB After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 145 KiB After Width: | Height: | Size: 145 KiB |
|
Before Width: | Height: | Size: 124 KiB After Width: | Height: | Size: 124 KiB |
|
Before Width: | Height: | Size: 143 KiB After Width: | Height: | Size: 143 KiB |
|
Before Width: | Height: | Size: 115 KiB After Width: | Height: | Size: 115 KiB |
|
Before Width: | Height: | Size: 126 KiB After Width: | Height: | Size: 126 KiB |
|
Before Width: | Height: | Size: 148 KiB After Width: | Height: | Size: 148 KiB |
|
Before Width: | Height: | Size: 123 KiB After Width: | Height: | Size: 123 KiB |
|
Before Width: | Height: | Size: 117 KiB After Width: | Height: | Size: 117 KiB |
|
Before Width: | Height: | Size: 104 KiB After Width: | Height: | Size: 104 KiB |
|
Before Width: | Height: | Size: 89 KiB After Width: | Height: | Size: 89 KiB |
|
Before Width: | Height: | Size: 92 KiB After Width: | Height: | Size: 92 KiB |
|
Before Width: | Height: | Size: 127 KiB After Width: | Height: | Size: 127 KiB |
|
Before Width: | Height: | Size: 153 KiB After Width: | Height: | Size: 153 KiB |
|
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 134 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 3.7 KiB After Width: | Height: | Size: 3.7 KiB |
|
Before Width: | Height: | Size: 4.5 KiB After Width: | Height: | Size: 4.5 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 4.0 KiB After Width: | Height: | Size: 4.0 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 3.9 KiB |
|
Before Width: | Height: | Size: 1.9 KiB After Width: | Height: | Size: 1.9 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 2.5 KiB After Width: | Height: | Size: 2.5 KiB |
|
Before Width: | Height: | Size: 2.8 KiB After Width: | Height: | Size: 2.8 KiB |
|
Before Width: | Height: | Size: 3.3 KiB After Width: | Height: | Size: 3.3 KiB |
|
Before Width: | Height: | Size: 2.2 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 2.3 KiB After Width: | Height: | Size: 2.3 KiB |
|
Before Width: | Height: | Size: 2.6 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 98 KiB After Width: | Height: | Size: 98 KiB |
|
Before Width: | Height: | Size: 325 KiB After Width: | Height: | Size: 325 KiB |
|
Before Width: | Height: | Size: 575 KiB After Width: | Height: | Size: 575 KiB |
|
Before Width: | Height: | Size: 203 KiB After Width: | Height: | Size: 203 KiB |
|
Before Width: | Height: | Size: 216 KiB After Width: | Height: | Size: 216 KiB |
|
Before Width: | Height: | Size: 156 KiB After Width: | Height: | Size: 156 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 10 KiB |
@@ -8,7 +8,7 @@ import json
|
|||||||
import bpy
|
import bpy
|
||||||
|
|
||||||
ROOT=Path(__file__).resolve().parent.parent
|
ROOT=Path(__file__).resolve().parent.parent
|
||||||
SOURCE=ROOT/'locenice'/'models'/'dum.glb'
|
SOURCE=ROOT/'models'/'dum.glb'
|
||||||
TARGET=Path(__file__).resolve().parent/'dum_locenice.blend'
|
TARGET=Path(__file__).resolve().parent/'dum_locenice.blend'
|
||||||
if not SOURCE.is_file():
|
if not SOURCE.is_file():
|
||||||
raise FileNotFoundError(SOURCE)
|
raise FileNotFoundError(SOURCE)
|
||||||
@@ -16,7 +16,7 @@ if TARGET.exists():
|
|||||||
raise FileExistsError(f'Rename or remove {TARGET} before running again.')
|
raise FileExistsError(f'Rename or remove {TARGET} before running again.')
|
||||||
bpy.ops.wm.read_factory_settings(use_empty=True)
|
bpy.ops.wm.read_factory_settings(use_empty=True)
|
||||||
bpy.ops.import_scene.gltf(filepath=str(SOURCE))
|
bpy.ops.import_scene.gltf(filepath=str(SOURCE))
|
||||||
defaults=json.loads((ROOT/'locenice'/'data'/'catalog.json').read_text())['defaults']
|
defaults=json.loads((ROOT/'data'/'catalog.json').read_text())['defaults']
|
||||||
scene=bpy.context.scene
|
scene=bpy.context.scene
|
||||||
scene.unit_settings.system='METRIC'
|
scene.unit_settings.system='METRIC'
|
||||||
scene.unit_settings.scale_length=1.0
|
scene.unit_settings.scale_length=1.0
|
||||||
@@ -60,6 +60,6 @@ Blender reorders glTF nodes, materials and textures. The included web manifest
|
|||||||
is indexed for the supplied GLB; the preparation tool rebinds stable IDs.
|
is indexed for the supplied GLB; the preparation tool rebinds stable IDs.
|
||||||
A changed wall or cabinet also requires checking web collision volumes / camera presets.
|
A changed wall or cabinet also requires checking web collision volumes / camera presets.
|
||||||
''')
|
''')
|
||||||
scene['locenice_metadata_json']=json.dumps(json.loads((ROOT/'locenice'/'data'/'scene.json').read_text()),ensure_ascii=False)
|
scene['locenice_metadata_json']=json.dumps(json.loads((ROOT/'data'/'scene.json').read_text()),ensure_ascii=False)
|
||||||
bpy.ops.wm.save_as_mainfile(filepath=str(TARGET))
|
bpy.ops.wm.save_as_mainfile(filepath=str(TARGET))
|
||||||
print('Saved:',TARGET)
|
print('Saved:',TARGET)
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
<?php
|
||||||
|
// Upload this whole folder, not only this file. No Node.js or database required.
|
||||||
|
header('Content-Type: text/html; charset=utf-8');
|
||||||
|
header('X-Content-Type-Options: nosniff');
|
||||||
|
$file = __DIR__ . '/app.html';
|
||||||
|
if (!is_readable($file)) {
|
||||||
|
http_response_code(500);
|
||||||
|
exit('Chybi app.html. Nahrajte celou slozku locenice2.');
|
||||||
|
}
|
||||||
|
readfile($file);
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
import assert from 'node:assert/strict';
|
import assert from 'node:assert/strict';
|
||||||
import {parseGLB,encodeGLB} from '../locenice/js/model-io.js';
|
import {parseGLB,encodeGLB} from '../js/model-io.js';
|
||||||
import {solarPosition} from '../locenice/js/solar.js';
|
import {solarPosition} from '../js/solar.js';
|
||||||
const root=new URL('../locenice/',import.meta.url);
|
const root=new URL('../',import.meta.url);
|
||||||
const bytes=new Uint8Array(fs.readFileSync(new URL('models/dum.glb',root)));
|
const bytes=new Uint8Array(fs.readFileSync(new URL('models/dum.glb',root)));
|
||||||
const {gltf,binary}=parseGLB(bytes);
|
const {gltf,binary}=parseGLB(bytes);
|
||||||
const catalog=JSON.parse(fs.readFileSync(new URL('data/catalog.json',root),'utf8'));
|
const catalog=JSON.parse(fs.readFileSync(new URL('data/catalog.json',root),'utf8'));
|
||||||
@@ -102,7 +102,7 @@ def rebind(source,edited,output,metadata=None):
|
|||||||
if __name__=='__main__':
|
if __name__=='__main__':
|
||||||
parser=argparse.ArgumentParser(description=__doc__)
|
parser=argparse.ArgumentParser(description=__doc__)
|
||||||
parser.add_argument('edited',type=Path);parser.add_argument('--out',type=Path,default=Path('prepared'))
|
parser.add_argument('edited',type=Path);parser.add_argument('--out',type=Path,default=Path('prepared'))
|
||||||
parser.add_argument('--source',type=Path,default=ROOT/'locenice'/'models'/'dum.glb')
|
parser.add_argument('--source',type=Path,default=ROOT/'models'/'dum.glb')
|
||||||
args=parser.parse_args()
|
args=parser.parse_args()
|
||||||
print(rebind(args.source,args.edited,args.out))
|
print(rebind(args.source,args.edited,args.out))
|
||||||
print('Back up the website first. Replace models/dum.glb AND data/scene.json together.')
|
print('Back up the website first. Replace models/dum.glb AND data/scene.json together.')
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
"""Optional: download pinned Three.js r180 locally, on a computer with internet.
|
"""Optional: download pinned Three.js r180 locally, on a computer with internet.
|
||||||
python tools/vendor_three.py
|
python tools/vendor_three.py
|
||||||
Then upload the generated locenice/vendor folder AND data/app-config.json.
|
Then upload the generated locenice2/vendor folder AND data/app-config.json.
|
||||||
Does not upload anything. No credentials or server-side installer required.
|
Does not upload anything. No credentials or server-side installer required.
|
||||||
"""
|
"""
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from urllib.request import Request, urlopen
|
from urllib.request import Request, urlopen
|
||||||
import json, re, hashlib
|
import json, re, hashlib
|
||||||
ROOT=Path(__file__).resolve().parent.parent/'locenice'
|
ROOT=Path(__file__).resolve().parent.parent
|
||||||
BASE='https://raw.githubusercontent.com/mrdoob/three.js/r180/'
|
BASE='https://raw.githubusercontent.com/mrdoob/three.js/r180/'
|
||||||
VENDOR=ROOT/'vendor'/'three-r180'
|
VENDOR=ROOT/'vendor'/'three-r180'
|
||||||
seen=set()
|
seen=set()
|
||||||