Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[epic] Mapbox and custom svg 0.4.8 #478

Merged
merged 28 commits into from
Feb 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
28 commits
Select commit Hold shift + click to select a range
4242dbe
fix save/load mapbox scene
Algorush Dec 29, 2023
6473fd5
save streetmix URLs as strings also
Algorush Jan 16, 2024
2eea31e
remove unnecessary checkings
Algorush Jan 16, 2024
881e699
fixed the filterJSON code
Algorush Jan 16, 2024
d4f5806
remove unnecessary variables
Algorush Jan 17, 2024
6304ffe
save src instead of id for external assets
Algorush Jan 29, 2024
d46c423
always save assets url in the street-assets
Algorush Jan 29, 2024
2e579fc
get assetsUrl during saving JSON
Algorush Jan 29, 2024
6539209
call json-utils.js from index.js
Algorush Feb 1, 2024
8500040
add inputStreetmix function to global STREET also
Algorush Feb 1, 2024
05fc582
add createEntities function to STREET global
Algorush Feb 1, 2024
4e9deaa
remove unnecessary attributes from filterJSONstreet func
Algorush Feb 2, 2024
9e3943f
call json-utils function from STREET.utils (inside component)
Algorush Feb 2, 2024
0212fb5
change filterJSON function for correct save/load
Algorush Feb 2, 2024
8f82240
create svg-extruder component
Algorush Feb 20, 2024
99c6da9
fix texture working
Algorush Feb 21, 2024
b30bc7c
add check for mesh before setting up texture parameters
Algorush Feb 21, 2024
0819b15
change ?? operator by ||
Algorush Feb 21, 2024
7b4c56b
Merge pull request #440 from 3DStreet/fix-saving-mapbox-scene
kfarr Feb 22, 2024
0436212
Merge pull request #465 from 3DStreet/fix-saving-user-modified-texture
kfarr Feb 23, 2024
1fdb988
Merge branch 'mapbox-and-custom-svg-epic' into load-jsonutils-from-in…
kfarr Feb 23, 2024
be3bafd
Merge pull request #468 from 3DStreet/load-jsonutils-from-indexjs
kfarr Feb 23, 2024
c60ba08
Merge pull request #474 from 3DStreet/extrude-svg-component
kfarr Feb 23, 2024
f80bcea
lint fix
kfarr Feb 23, 2024
82005b9
version bump to 0.4.8 and run dist
kfarr Feb 23, 2024
c8852ff
again 0.4.8 and dist bump
kfarr Feb 23, 2024
01065fe
fix saving JSON if src dont have value.src key
Algorush Feb 24, 2024
e2bd933
dist bump for bug fix
kfarr Feb 24, 2024
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions dist/aframe-street-component.js

Large diffs are not rendered by default.

7 changes: 2 additions & 5 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,6 @@
<!-- mapbox -->
<script src="./src/lib/aframe-mapbox-component.min.js"></script>

<!-- save / load -->
<script src="./src/json-utils.js"></script>

<!-- vr teleport controls -->
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/aframe-blink-controls.min.js"></script>

Expand Down Expand Up @@ -68,7 +65,7 @@
<div class="right-fixed">
<ul class="right-menu">
<li onclick="buttonScreenshotTock()"> <a class="camera" href="#"> <span> Capture image as PNG </span> <img src="ui_assets/camera-icon.svg"> </a></li>
<li onclick="inputStreetmix()"> <a class="load" href="#"> <span> Load Streetmix URL </span> <img src="ui_assets/streetmix-logo.svg"> </a></li>
<li onclick="STREET.utils.inputStreetmix()"> <a class="load" href="#"> <span> Load Streetmix URL </span> <img src="ui_assets/streetmix-logo.svg"> </a></li>
<!-- <li onclick="inputJSON()"> <a class="load" href="#"> <span> Load JSON String </span> <img src="assets/ui_assets/upload-icon.svg"> </a></li> -->
<li><a class="load"> <label for="inputfile" style="display: inherit; align-items: center; cursor: pointer"> <input type="file" id="inputfile" style="display:none" accept=".js, .json, .txt"> <span> Load JSON File </span> <img src="ui_assets/upload-icon.svg"></label></a></li>
</ul>
Expand Down Expand Up @@ -123,7 +120,7 @@
<script>

document.getElementById('inputfile')
.addEventListener('change', fileJSON);
.addEventListener('change', STREET.utils.fileJSON);

function buttonScreenshotTock() {
const screenshotEl = document.getElementById('screenshot');
Expand Down
107 changes: 17 additions & 90 deletions mapbox.html
Original file line number Diff line number Diff line change
Expand Up @@ -98,17 +98,17 @@
streetmix-loader="streetmixStreetURL: https://streetmix.net/scott/31/south-van-ness-idea-short-term; showBuildings: false;"
></a-entity>

<a-entity id="environment" data-layer-name="Environment" street-environment="preset: day;"></a-entity>

<a-entity id="cameraRig" position="0 10 30" data-layer-name="Viewer" cursor-teleport="cameraRig: #cameraRig; cameraHead: #camera;" look-controls="reverseMouseDrag: true" wasd-controls="enabled: true">
<a-entity id="camera" camera="far: 1000" position="0 1.6 0" ></a-entity>
<a-entity id="leftHand" hand-controls="hand: left;" blink-controls="cameraRig: #cameraRig; teleportOrigin: #camera; rotateOnTeleport:false;"></a-entity>
<a-entity id="rightHand" hand-controls="hand: right" blink-controls="cameraRig: #cameraRig; teleportOrigin: #camera; rotateOnTeleport:false;"></a-entity>
<a-entity id="screenshot" class="no-pause" screentock visible="false"></a-entity>
</a-entity>
</a-entity>

<a-entity id="cameraRig" position="0 10 30" data-layer-name="Viewer" cursor-teleport="cameraRig: #cameraRig; cameraHead: #camera;" look-controls="reverseMouseDrag: true" wasd-controls="enabled: true">
<a-entity id="camera" camera="far: 1000" position="0 1.6 0" ></a-entity>
<a-entity id="leftHand" hand-controls="hand: left;" blink-controls="cameraRig: #cameraRig; teleportOrigin: #camera; rotateOnTeleport:false;"></a-entity>
<a-entity id="rightHand" hand-controls="hand: right" blink-controls="cameraRig: #cameraRig; teleportOrigin: #camera; rotateOnTeleport:false;"></a-entity>
<a-entity id="screenshot" class="no-pause" screentock visible="false"></a-entity>
</a-entity>

<a-entity id="environment" data-layer-name="Environment" street-environment="preset: day;"></a-entity>

<a-entity id="reference-layers" data-layer-name="Reference Layers" data-layer-show-children>
<a-entity
data-layer-name="Mapbox Satellite Streets"
Expand All @@ -126,103 +126,30 @@
</a-scene>
</body>
<script>
// only show VR button if headset connected
AFRAME.registerComponent('vr-mode-ui-if-headset', {
dependencies: ['vr-mode-ui'],
init: function () {
if (!AFRAME.utils.device.checkHeadsetConnected()) {
this.el.setAttribute('vr-mode-ui', 'enabled', false);
}
}
})

AFRAME.registerComponent('set-loader-from-hash', {
dependencies: ['streetmix-loader'],
schema: {
defaultURL: { type: 'string' }
},
init: function () {
// get hash from window
const streetURL = window.location.hash.substring(1);
if (streetURL !== undefined && streetURL.length > 0) {
console.log('[set-loader-from-hash]','Using URL from hash', streetURL)
this.el.setAttribute('streetmix-loader', 'streetmixStreetURL', streetURL);
}
// else {
// console.log('[set-loader-from-hash]','Using default URL', this.data.defaultURL)
// this.el.setAttribute('streetmix-loader', 'streetmixStreetURL', this.data.defaultURL);
// }
}
});
document.getElementById('inputfile')
.addEventListener('change', fileJSON);

function screenshot() {
AFRAME.scenes[0].setAttribute('screenshot','width',AFRAME.scenes[0].canvas.width)
AFRAME.scenes[0].setAttribute('screenshot','height',AFRAME.scenes[0].canvas.height)
document.querySelector('a-scene').components.screenshot.capture('perspective');
function buttonScreenshotTock() {
const screenshotEl = document.getElementById('screenshot');
screenshotEl.play(); // double check playing in case we're in editor mode
screenshotEl.setAttribute('screentock', 'type', 'jpg');
screenshotEl.setAttribute('screentock', 'takeScreenshot', true);
}

function startEditor() {
var sceneEl = document.querySelector('a-scene');
sceneEl.components.inspector.openInspector();
document.querySelector('.viewer-header-wrapper').style.display = 'none';
}

AFRAME.registerComponent('timed-inspector', {
init: function() {
setTimeout( function () {
window.postMessage('INJECT_AFRAME_INSPECTOR')
}, this.data * 1000)
}
});

function inputStreetmix() {
streetmixURL = prompt("Please enter a Streetmix URL", "https://streetmix.net/kfarr/3/example-street");
setTimeout(function() { window.location.hash = streetmixURL; });
streetContainerEl = document.getElementById('street-container');
while (streetContainerEl.firstChild) {
streetContainerEl.removeChild(streetContainerEl.lastChild);
}
streetContainerEl.innerHTML = '<a-entity street streetmix-loader="streetmixStreetURL: '+streetmixURL+'""></a-entity>';
}

// JSON loading starts here
function getValidJSON(stringJSON) {
// Preserve newlines, etc. - use valid JSON
// Remove non-printable and other non-valid JSON characters
return stringJSON.replace(/\'/g, "")
.replace(/\n/g, "")
.replace(/[\u0000-\u0019]+/g,"");
}

function createElementsFromJSON(streetJSONString) {
const validJSONString = getValidJSON(streetJSONString);
streetContainerEl = document.getElementById('street-container');
while (streetContainerEl.firstChild) {
streetContainerEl.removeChild(streetContainerEl.lastChild);
}
var streetObject = JSON.parse(validJSONString);
createEntities(streetObject.data, streetContainerEl);
}

function inputJSON() {
const stringJSON = prompt("Please paste 3DStreet JSON string");
if (stringJSON) {
createElementsFromJSON(stringJSON);
}
}

function fileJSON() {
let reader=new FileReader();
reader.onload=function(){
createElementsFromJSON(reader.result);
}
reader.readAsText(this.files[0]);
}

document.getElementById('inputfile')
.addEventListener('change', fileJSON);
});
</script>
<!-- <script src="./dist/3dstreet-editor.js"></script> -->

<!-- Google Analytics - Global site tag (gtag.js) -->
<script async src="https://www.googletagmanager.com/gtag/js?id=G-T65XPDLZ3F"></script>
Expand Down
4 changes: 2 additions & 2 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "3dstreet",
"version": "0.4.6",
"version": "0.4.8",
"description": "Web-based 3D visualization of streets using A-Frame and WebXR",
"main": "dist/aframe-street-component.js",
"scripts": {
Expand Down
7 changes: 6 additions & 1 deletion src/assets.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/* global AFRAME, customElements */

function buildAssetHTML (assetUrl, categories) {
if (!assetUrl) assetUrl = 'https://assets.3dstreet.app/';
// if (!assetUrl) assetUrl = 'https://assets.3dstreet.app/';
console.log('[street]', 'Using street assets from', assetUrl);
const surfacesRoughness = 0.8;
var assetsObj = {
Expand Down Expand Up @@ -295,7 +295,12 @@ class StreetAssets extends AFRAME.ANode {
const self = this;
var categories = this.getAttribute('categories');
var assetUrl = this.getAttribute('url');
if (!assetUrl) {
assetUrl = 'https://assets.3dstreet.app/';
this.setAttribute('url', assetUrl);
}
const assetsHTML = buildAssetHTML(assetUrl, categories);

this.insertAdjacentHTML('afterend', assetsHTML);

AFRAME.ANode.prototype.load.call(self);
Expand Down
106 changes: 106 additions & 0 deletions src/components/svg-extruder.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
/* global AFRAME */
var { SVGLoader } = require('../lib/SVGLoader.js');

AFRAME.registerComponent('svg-extruder', {
schema: {
svgString: { type: 'string' },
depth: { type: 'number', default: 4 }
},
init: function () {
const el = this.el;
const svgString = this.data.svgString;
this.loader = new SVGLoader();

el.addEventListener('materialtextureloaded', () => {
// fix texture properties to correctly show texture for extruded mesh
const extrudedMesh = el.getObject3D('mesh');
if (extrudedMesh && extrudedMesh.material) {
const texture = extrudedMesh.material.map;
texture.wraps = texture.wrapt = THREE.repeatwrapping;
texture.repeat.set(1 / 100, 1 / 100);
texture.offset.set(0.1, 0.5);
}
});

if (svgString) {
this.extrudeFromSVG(svgString);
el.setAttribute('material', 'src:#grass-texture;repeat:5 5;roughness:1');
el.setAttribute('scale', '0.05 0.05 0.05');
el.setAttribute('shadow', 'cast: true; receive: true');
}
},
extrudeFromSVG: function (svgString) {
const depth = this.data.depth;
const el = this.el;
const svgData = this.loader.parse(svgString);
const fillMaterial = new THREE.MeshStandardMaterial({ color: '#F3FBFB' });
const stokeMaterial = new THREE.LineBasicMaterial({
color: '#00A5E6'
});

const extrudeSettings = {
depth: depth,
bevelEnabled: false
};

// svgGroup.scale.y *= -1;
let shapeIndex = 0;

const shapeGeometryArray = [];

svgData.paths.forEach((path) => {
const shapes = SVGLoader.createShapes(path);

shapes.forEach((shape) => {
const geometry = new THREE.ExtrudeGeometry(shape, extrudeSettings);
shapeGeometryArray.push(geometry);

const linesGeometry = new THREE.EdgesGeometry(geometry);
const lines = new THREE.LineSegments(linesGeometry, stokeMaterial);

el.setObject3D('lines' + shapeIndex, lines);
lines.name = 'lines' + shapeIndex;
shapeIndex += 1;
});
});

// Merge array of extruded geometries into the mergedGeometry
const mergedGeometry =
THREE.BufferGeometryUtils.mergeBufferGeometries(shapeGeometryArray);

mergedGeometry.computeVertexNormals();

// Finally, create a mesh with the merged geometry
const mergedMesh = new THREE.Mesh(mergedGeometry, fillMaterial);

// remove existing mesh from entity
el.removeObject3D('mesh');

el.setObject3D('mesh', mergedMesh);

const box = new THREE.Box3().setFromObject(mergedMesh);
const size = box.getSize(new THREE.Vector3());

const zOffset = size.y / -2;
const xOffset = size.x / -2;

// Offset all of extruded elements, to center them
el.object3D.children.forEach((item) => {
item.position.x = xOffset;
item.position.y = zOffset;
});

el.object3D.rotateX(Math.PI / 2);
},
update: function (oldData) {
// If `oldData` is empty, then this means we're in the initialization process.
// No need to update.
if (Object.keys(oldData).length === 0) { return; }

const svgString = this.data.svgString;

if (svgString) {
this.extrudeFromSVG(svgString);
}
}
});
2 changes: 2 additions & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,10 @@ require('babel-polyfill');
if (typeof VERSION !== 'undefined') { console.log(`3DStreet Version: ${VERSION} (Date: ${new Date(COMMIT_DATE).toISOString().split('T')[0]}, Commit Hash: #${COMMIT_HASH})`); }
var streetmixParsers = require('./aframe-streetmix-parsers');
var streetmixUtils = require('./tested/streetmix-utils');
require('./json-utils.js');
require('./components/gltf-part');
require('./components/ocean');
require('./components/svg-extruder.js');
require('./lib/aframe-cursor-teleport-component.min.js');
require('./lib/animation-mixer.js');
require('./assets.js');
Expand Down
Loading
Loading