<div class="fixed-ratio">
<!-- VueGL scéna -->
<vgl-renderer antialias>
<vgl-scene background-color="#fff">
<vgl-text-geometry
name="textGeometry"
font="../../../libs/threejs/three.helvetiker.json"
size="2"
height="1"
:text="text">
</vgl-text-geometry>
<vgl-mesh-standard-material
name="material"
:color="diffuseColor">
</vgl-mesh-standard-material>
<vgl-mesh
geometry="textGeometry"
material="material"
position="0 0 0">
</vgl-mesh>
<vgl-ambient-light
:color="ambientColor"
intensity="0.5">
</vgl-ambient-light>
<vgl-directional-light
color="#fff"
position="0 4 2"
intensity="2">
</vgl-directional-light>
</vgl-scene>
<vgl-perspective-camera
orbit-position="16 1.4 0"
orbit-target="5 0 0">
</vgl-perspective-camera>
</vgl-renderer>
</div>
<div>
<!-- Formulář pro ovládání scény -->
<form>
<div>
<label>Text</label>
<!-- Vstup pro text s obousměrným data-bindingem v-model -->
<input type="text" v-model="text" />
</div>
<div class="grid">
<div>
<label>Základní barva</label>
<div>
<input type="color" v-model="diffuseColor" />
<span :style="'color: ' + diffuseColor"> {{ diffuseColor }} </span>
</div>
</div>
<div>
<label>Barva lesku</label>
<div>
<input type="color" v-model="ambientColor" />
<span :style="'color: ' + ambientColor"> {{ ambientColor }} </span>
</div>
</div>
</div>
</form>
</div>
// Inicializace VueGL komponentů
Object.keys(VueGL).forEach((key) => {
Vue.component(key, VueGL[key]);
});
// Orbitální kamera
function OrbitCamera(canvasId) {
var canvas = document.getElementById(canvasId);
var controls = new THREE.OrbitControls(canvas.__vue__.vglNamespace.cameras.active, canvas);
function update() {
requestAnimationFrame(update);
controls.update();
canvas.__vue__.vglNamespace.update();
}
update();
}
ready(function () {
new OrbitCamera("canvas1");
});
// Vue aplikace
var app1 = new Vue({
el: '#app1',
data: {
text: 'Hello world!',
diffuseColor: '#dd3300',
ambientColor: '#ee9966'
}
});
<div class="fixed-ratio">
<!-- VueGL scéna -->
<vgl-renderer antialias>
<vgl-scene background-color="#222">
<!-- Cyklus s využitím directivy v-for pro vykreslení všech kostek -->
<vgl-group v-for="(item, index) in items">
<vgl-box-geometry
:name="'box' + index"
:width="item.size.x"
:height="item.size.y"
:depth="item.size.z">
</vgl-box-geometry>
<vgl-mesh-standard-material
:name="'material' + index"
:color="item.color">
</vgl-mesh-standard-material>
<vgl-mesh
:geometry="'box' + index"
:material="'material' + index"
:position="(((index - ((items.length - 1) / 2)) * 2) + (item.position.x * 1)) + ' ' + item.position.y + ' ' + item.position.z">
</vgl-mesh>
</vgl-group>
<vgl-ambient-light
color="#fff"
intensity="0.5">
</vgl-ambient-light>
<vgl-directional-light
color="#fff"
position="0 4 2"
intensity="2">
</vgl-directional-light>
</vgl-scene>
<vgl-perspective-camera
orbit-position="10 1.4 0"
orbit-target="0 0 0">
</vgl-perspective-camera>
</vgl-renderer>
</div>
<div>
<!-- Formulář pro ovládání scény -->
<form>
<ul>
<!-- Cyklus s využitím directivy v-for pro ovládací panely ke všem kostkám -->
<li v-for="(item, index) in items">
<div class="grid">
<div>
<label>Objekt #{{index + 1}}</label>
<div>
<input type="color" v-model="item.color" />
<span :style="'color: ' + item.color"> {{ item.color }} </span>
</div>
</div>
<div>
<label>Šířka {{ Math.floor(item.size.x * 100) }}%</label>
<input type="range" v-model="item.size.x" min="0.1" max="2" step="0.1" />
</div>
<div>
<label>Výška {{ Math.floor(item.size.y * 100) }}%</label>
<input type="range" v-model="item.size.y" min="0.1" max="2" step="0.1" />
</div>
<div>
<label>Délka {{ Math.floor(item.size.z * 100) }}%</label>
<input type="range" v-model="item.size.z" min="0.1" max="2" step="0.1" />
</div>
<div>
<label>X {{ item.position.x }}</label>
<input type="range" v-model="item.position.x" min="-1" max="1" step="0.1" />
</div>
<div>
<label>Y {{ item.position.y }}</label>
<input type="range" v-model="item.position.y" min="-1" max="1" step="0.1" />
</div>
<div>
<label>Z {{ item.position.z }}</label>
<input type="range" v-model="item.position.z" min="-1" max="1" step="0.1" />
</div>
<div>
<!-- Tlačítko napojené na metodu pro smazání kostky -->
<a v-on:click="remove(index)">Smazat</a>
</div>
</div>
</li>
</ul>
<!-- Tlačítko napojené na metodu pro přidání kostky -->
<a v-on:click="add()" > Přidat nový objekt</a>
</form>
</div>
// Inicializace VueGL komponentů
Object.keys(VueGL).forEach((key) => {
Vue.component(key, VueGL[key]);
});
// Orbitální kamera
function OrbitCamera(canvasId) {
var canvas = document.getElementById(canvasId);
var controls = new THREE.OrbitControls(canvas.__vue__.vglNamespace.cameras.active, canvas);
function update() {
requestAnimationFrame(update);
controls.update();
canvas.__vue__.vglNamespace.update();
}
update();
}
ready(function () {
new OrbitCamera("canvas2");
});
// Vue aplikace
var app2 = new Vue({
el: '#app2',
data: {
items: [],
},
methods: {
// metoda pro přidání kostky
add: function () {
this.items.push({
size: { x: 1, y: 1, z: 1 },
position: { x: 0, y: 0, z: 0 },
color: getRandomColor()
});
},
// metoda pro smazání kostky
remove: function (index) {
this.items.splice(index, 1);
}
},
// metoda volaná při inicializaci
created: function () {
this.add();
this.add();
}
});
<vgl-renderer antialias id="canvas3">
<vgl-scene background-color="#222" name="leds">
<vgl-box-geometry name="plane" width="16" height="0.1" depth="6"></vgl-box-geometry>
<vgl-mesh-standard-material name="planeMaterial" color="#0D660D"></vgl-mesh-standard-material>
<vgl-mesh geometry="plane" material="planeMaterial" position="0 0 0"></vgl-mesh>
<vgl-mesh-standard-material name="goldMaterial" color="#FF9900"></vgl-mesh-standard-material>
<vgl-text-geometry name="textLed" font="../../../libs/threejs/three.helvetiker.json" size="0.75" height="0.1" text="LED diody (8 bitu)"></vgl-text-geometry>
<vgl-mesh geometry="textLed" material="goldMaterial" position="-4.05 0 -1.6" rotation="-1.5707963268, 0, 0"></vgl-mesh>
<vgl-mesh-standard-material name="ledMaterialOff" color="#CCCCCC"></vgl-mesh-standard-material>
<vgl-mesh-standard-material name="ledMaterialOn" :color="color"></vgl-mesh-standard-material>
<vgl-sphere-geometry name="sphere" radius="0.45" width-segments="16" height-segments="16"></vgl-sphere-geometry>
<vgl-cylinder-geometry name="cylinder" radius-top="0.45" radius-bottom="0.45" height="1" radial-segments="16" height-segments="1" />
<vgl-cylinder-geometry name="bottom" radius-top="0.5" radius-bottom="0.5" height="0.16" radial-segments="16" height-segments="1" />
<vgl-mesh-standard-material name="buttonBottomMaterial" color="#1A1A1A"></vgl-mesh-standard-material>
<vgl-box-geometry name="buttonBottom" width="1" height="0.4" depth="1"></vgl-box-geometry>
<vgl-mesh-standard-material name="buttonMaterial" color="#8080CC"></vgl-mesh-standard-material>
<vgl-group v-for="(led, index) in leds">
<vgl-group :position="((((leds.length - index) - (leds.length / 2)) * 2) - 1) + ' 0 0'">
<vgl-mesh geometry="sphere" :material="(led.state ? 'ledMaterialOn' : 'ledMaterialOff')" position="0 1 0"></vgl-mesh>
<vgl-mesh geometry="cylinder" :material="(led.state ? 'ledMaterialOn' : 'ledMaterialOff')" position="0 0.5 0"></vgl-mesh>
<vgl-mesh geometry="bottom" :material="(led.state ? 'ledMaterialOn' : 'ledMaterialOff')" position="0 0.08 0"></vgl-mesh>
<vgl-text-geometry :name="'textLed' + index" font="../../../libs/threejs/three.helvetiker.json" size="0.5" height="0.1" :text="(Math.pow(2, index)).toString()"></vgl-text-geometry>
<vgl-mesh :geometry="'textLed' + index" material="goldMaterial" position="0 0 1.2" rotation="-1.5707963268, 0, 0"></vgl-mesh>
<vgl-group position="0 0.1 2">
<vgl-mesh geometry="buttonBottom" material="buttonBottomMaterial" position="0 0.08 0"></vgl-mesh>
<vgl-cylinder-geometry :name="'buttonLed' + index" :height="(led.state ? 0.2 : 0.6)" radius-top="0.4" radius-bottom="0.4" radial-segments="16" height-segments="1" />
<vgl-clickable-mesh :onclick="(function () { lightSwitch(index); })" :geometry="'buttonCylinder' + index" material="buttonMaterial" position="0 0.35 0"></vgl-clickable-mesh>
</vgl-group>
</vgl-group>
</vgl-group>
<vgl-ambient-light color="#fff" intensity="0.5"></vgl-ambient-light>
<vgl-directional-light color="#fff" position="0 4 2" intensity="2"></vgl-directional-light>
</vgl-scene>
<vgl-perspective-camera name="active" orbit-position="12 1.4 0" orbit-target="0 0 0">
</vgl-perspective-camera>
</vgl-renderer>
// VueGL komponent pro klikatelný objekt
VueGL.VglClickableMesh = {
mixins: VueGL.VglMesh.mixins,
props: ['onclick', "geometry", "material"],
computed: {
inst: () => new THREE.Mesh()
},
created: function () {
this.inst.onclick = this.$props.onclick;
},
name: "VglClickableMesh"
};
// VueGL komponent pro průhledný materiál
VueGL.VglTransparentMaterial = {
mixins: VueGL.VglMeshStandardMaterial.mixins,
props: ['opacity', "color", "name"],
computed: {
inst: () => new THREE.MeshStandardMaterial()
},
watch: {
inst: {
handler: function (inst) { inst.color.setStyle(this.color); },
immediate: true,
},
color: function (newColor) {
this.inst.color.setStyle(newColor);
this.update();
}
},
created: function () {
this.inst.depthWrite = false;
this.inst.transparent = true;
this.inst.opacity = this.$props.opacity;
},
name: "VglTransparentMaterial"
};
// Inicializace VueGL komponent
Object.keys(VueGL).forEach((key) => {
Vue.component(key, VueGL[key]);
});
// Orbitální kamera
function OrbitCamera(canvasId) {
var canvas = document.getElementById(canvasId);
var controls = new THREE.OrbitControls(canvas.__vue__.vglNamespace.cameras.active, canvas);
function update() {
requestAnimationFrame(update);
controls.update();
canvas.__vue__.vglNamespace.update();
}
update();
}
// Klikání na objekty pomocí parpsku
function RayCasterClicker(canvasId, scene) {
var canvas = document.getElementById(canvasId);
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
var rect = canvas.getBoundingClientRect();
canvas.addEventListener("click", function (e) {
mouse.x = ((event.clientX - rect.left) / rect.width) * 2 - 1;
mouse.y = - ((event.clientY - rect.top) / rect.height) * 2 + 1;
raycaster.setFromCamera(mouse, canvas.__vue__.vglNamespace.cameras.active);
var intersects = raycaster.intersectObjects(canvas.__vue__.vglNamespace.scenes[scene].children, true);
if (intersects.length > 0) {
var i = 0, clicked = false;
while (i < intersects.length || !clicked) {
if (intersects[i].object.onclick) {
clicked = true;
intersects[i].object.onclick();
}
i++;
}
}
});
}
ready(function () {
new OrbitCamera("canvas3");
new RayCasterClicker("canvas3", "leds");
});
// Vue aplikace
var app3 = new Vue({
el: '#app3',
data: {
leds: [
{ state: false },
{ state: true },
{ state: false },
{ state: false },
{ state: true },
{ state: true },
{ state: false },
{ state: false },
],
color: '#ff0000',
},
// dopočítáváné vlastnosti pro hexadecimální a binární zápis
computed: {
int: {
get: function () {
var r = 0;
for (var i = 0; i < this.leds.length; i++) {
r += this.leds[i].state ? Math.pow(2, i) : 0;
}
return r;
},
set: function (v) {
var bin = toBin(v);
for (var i = 0; i < this.leds.length; i++) {
this.leds[this.leds.length - i - 1].state = bin[i] == "1";
}
}
},
hex: {
get: function () { return toHex(this.int); },
set: function (v) { this.int = parseInt(v, 16); }
},
bin: {
get: function () { return toBin(this.int); },
set: function (v) { this.int = parseInt(v, 2); }
}
},
methods: {
// metoda pro přepnutí LED diody
lightSwitch: function (index) {
this.leds[index].state = !this.leds[index].state;
}
}
});