Jako inspiraci k našemu semestrálnímu projektu jsme si vybrali Smetanovo náměstí v Litomyšli. Vybrali jsme se toto místo pro jeho unikátnost a malebnost. Toto náměstí je proslavené svou architekturou, která mu dodává jedinečnou charakteristiku stejně jako jeho ústřední věž.
Pro vytvoření dostatečně detailních modelů budov a dalších prvků obklopujících náměstí jsme se ho snažili přesně nafotit, abychom se dále rozhodli pro další postup. Během projektu je možné že se rozhodneme upravit či změnit některé modely, neboť stávající rozhodnutí nebude dostačující pro tento předmět či nebude naplňovat naše představy.
Zde můžeme nalézt základní fotodokumentaci Smetanova náměstí, které se budeme snažit zvirtualizovat během tohoto semestru.
Tyto prvky byly vybrány na základě jejich možností pro určtou interaktivitu při jejich přiblížení, či aktivací pomocí mouse-overu či jiné akce.
Dané budovy byly vybrány jako základy pro jejich vymodelování pomocí gramatik a jejich variací kolem náměstí.
Dané budovy byly vybrány jako vzory pro 3D rekonstrukci v programu od společnosti Google, využijeme několik možných pohledů pro přesnější model.
Objekty jako lampa pouličního osvětlení, lavička a parkovací automat byly vybrány pro 3D rekonstrukci, bude však potřeba dodat i další detailnější fotografie.
Náhled na tento model ve fullscreen v novém tabu
Zde je možné stáhnout všechny soubory k celkové scéně. Celková VRML scéna ke stažení ▼
Nebyly přidány šipky, neboť způsobovaly nestabilitu celé scény. Avšak byly vytvořeny viz.
Náhled na tuto dynamickou scénu ve fullscreen v novém tabu
Hlavní skript ovládající scénu a dynamické akce.
function init(){
var hydrant = new initT('Hydrant2');
var
hydrant2 = new initT('Hydrant3');
listenerT(hydrant);
listenerT(hydrant2);
var parkomat =
new initT('Parkomat2');
var parkomat2 = new initT('Parkomat3');
listenerT(parkomat);
listenerT(parkomat2);
var
kytka = new initT('Kytka1');
listenerT(kytka);
var lampa =
new initLampa('Lampa2');
var lampa2 = new initLampa('Lampa3');
listenerLampa(lampa);
listenerLampa(lampa2);
var
vlajka=new initVlajka('Vlajka1');
listenerVlajka(vlajka);
var kobra=new initKobra('Kobra1');
listenerKobra(kobra);
ghosts=[
new GhostTouch(hydrant),
new GhostTouch(hydrant2),
new
GhostTouch(parkomat),
new GhostTouch(parkomat2),
new GhostTouch(kytka),
new GhostTouch(lampa),
new GhostTouch(lampa2),
new GhostTouch(kobra),
new
GhostHover(vlajka)];
gt=new initGhostsToogle(ghosts);
listenerGhostsToogle(gt);
time=new initTime();
initTimeToggle(time);
}
function initGhostsToogle(aa){
this.st=false;
this.fn=function(){
getRandom(aa).method();
}
}
function listenerGhostsToogle(gt){
el=document.getElementById('ghostsToggle');
el.addEventListener('click',function(){
console.log('click');
if(gt.st){
gt.st=false;
clearInterval(gt.int);
}else{
gt.st=true;
gt.int=setInterval(gt.fn,5000);
}
});
}
function GhostTouch(element){
this.method=function(){
eventFire(element.element,
'click');
}
}
function GhostHover(element){
this.st=false;
var me=this;
this.method=function(){
if(me.st){
me.st=false;
eventFire(element.element, 'mouseout');
}else{
me.st=true;
eventFire(element.element, 'mouseover');
}
}
}
function getRandom(elements){
return
elements[Math.floor(Math.random() * elements.length)];
}
function initTime(){
this.day=0;
this.hour=0;
this.sun=document.getElementById('lit__DLL');
this.minute=0;
this.hud=document.getElementById('time');
var me=this;
this.func=function(){
me.minute=me.minute+12;
if(me.minute>60){
me.hour++;
me.minute=me.minute%60;
}
if(me.hour>=24){
me.day++;
me.hour=me.hour%24;
}
o=((60*(me.hour+18)+me.minute)/24/60)*2*Math.PI;
me.sun.setAttribute('direction',[-Math.cos(o),-Math.sin(o),0].join());
setTime(me.hud,me.day,me.hour,me.minute);
}
this.t=setInterval(this.func,1000);
}
function initTimeToggle(t){
paused=false;
document.getElementById('timeToggle').addEventListener('click',function(){
if(paused){
paused=false;
t.t=setInterval(t.func,1000);
}else{
paused=true;
clearInterval(t.t)
}
});
}
function
setTime(hud,day,hour, minute){
hud.innerHTML=String(day)+', '+pad(hour,2)+':'+pad(minute,2);
}
function pad(num, size) {
var s =
num+"";
while (s.length
< size) s = "0" +
s;
return s;
}
function
initKobra(id){
this.element=document.getElementById(id);
this.or=getInlinedElement(id,'Or');
this.t=[0,1,0,0];
}
function listenerKobra(h){
h.element.addEventListener('click',function(){
vals=h.or.getAttribute('destination').split(',');
h.t[3]=h.t[3]+1.54;
console.log(h.or.getAttribute('destination'));
h.or.setAttribute('destination',h.t.join());
});
}
function initVlajka(id){
this.element=document.getElementById(id);
this.start=getInlinedElement(id,'TiS');
this.sound=getInlinedElement(id,'AC');
this.url=this.sound.getAttribute('url');
this.sound.setAttribute('loop','true')
this.start.setAttribute('startTime',(new Date()).getTime()/1000);
this.start.setAttribute('pauseTime',(new Date()).getTime()/1000);
this.sound.setAttribute('pauseTime',(new Date()).getTime()/1000);
this.sound.setAttribute('url','')
}
function
listenerVlajka(h){
h.element.addEventListener('mouseover',function(){
h.sound.setAttribute('url',h.url)
h.start.setAttribute('resumeTime',(new Date()).getTime()/1000);
h.sound.setAttribute('resumeTime',(new Date()).getTime()/1000);
});
h.element.addEventListener('mouseout',function(){
console.log('out')
h.sound.setAttribute('url','')
h.start.setAttribute('pauseTime',(new Date()).getTime()/1000);
h.sound.setAttribute('pauseTime',(new Date()).getTime()/1000);
});
}
function initT(id){
this.element=document.getElementById(id);
this.start=getInlinedElement(id,'TiS');
this.sound=getInlinedElement(id,'AC');
this.url=this.sound.getAttribute('url');
this.sound.setAttribute('pauseTime',(new
Date()).getTime()/1000);
this.sound.setAttribute('url','');
}
function listenerT(h){
h.element.addEventListener('click', function() {
console.log('click')
h.start.setAttribute('startTime',(new Date()).getTime()/1000);
h.sound.setAttribute('url',h.url)
h.sound.setAttribute('stopTime',(new Date()).getTime()/1000);
h.sound.setAttribute('startTime',(new
Date()).getTime()/1000);
});
}
function initLampa(id){
this.element=document.getElementById(id);
this.start=getInlinedElement(id,'TiS');
this.sound=getInlinedElement(id,'AC');
this.light=getInlinedElement(id,'SL');
this.color=getInlinedElement(id,'Color_low');
this.color2=getInlinedElement(id,'Color_high');
this.url=this.sound.getAttribute('url');
this.sound.setAttribute('pauseTime',(new Date()).getTime()/1000);
this.sound.setAttribute('url','');
this.start_color=this.color.getAttribute('diffuseColor');
this.active=false;
}
function listenerLampa(h){
h.element.addEventListener('click', function() {
console.log('click')
if(h.active){
h.light.setAttribute('on',false);
h.color.setAttribute('diffuseColor',h.start_color);
h.color2.setAttribute('diffuseColor',h.start_color);
h.active=false;
}
else{
h.start.setAttribute('startTime',(new
Date()).getTime()/1000);
h.sound.setAttribute('url',h.url);
h.sound.setAttribute('stopTime',(new Date()).getTime()/1000);
h.sound.setAttribute('startTime',(new Date()).getTime()/1000);
h.light.setAttribute('on',true);
h.active=true;
}
});
}
function eventFire(el, etype){
if (el.fireEvent) {
(el.fireEvent('on' + etype));
} else
{
var evObj
= document.createEvent('Events');
evObj.initEvent(etype,
true, false);
el.dispatchEvent(evObj);
}
}
Zpracovává prota do scény.
function processProtos(x3dNode) {
var protos = x3dNode.getElementsByTagName('ExternProtoDeclare');
if (protos.length === 0) {
protos = x3dNode.getElementsByTagName('externprotodeclare');
}
console.log(protos.length,
'Externproto declare found');
for (var i = 0; i
< protos.length; i++) {
var
proto = loadExternProto(protos[i]);
if (proto)
{
//console.log('new extern proto',i,proto);
protos[i].parentNode.appendChild(proto);
protos[i].parentNode.removeChild(protos[i]);
i--;
}
}
protos = x3dNode.getElementsByTagName('ProtoDeclare');
if (protos.length === 0) {
protos = x3dNode.getElementsByTagName('protodeclare');
}
console.log(protos.length, 'proto
declare found');
for
(var i = 0; i <
protos.length; i++) {
loadProto(x3dNode, protos[i]);
}
console.log(x3dNode.nodeName, x3dNode.childNodes.length);
}
function loadExternProto(externproto) {
var protoUrl = externproto.getAttribute('url');
protoUrl = protoUrl.replace(/"/g,
'');
var idx
= protoUrl.indexOf("#");
var
name = protoUrl.substr(idx + 1);
protoUrl = protoUrl.substr(0, idx);
console.log('loading', protoUrl, name);
var p =
null;
var scene
= loadX3DScene(protoUrl);
console.log('loaded',
scene);
if (scene
!== undefined && scene) {
var protos = scene.getElementsByTagName('ProtoDeclare');
if
(protos.length === 0) {
protos = scene.getElementsByTagName('protodeclare');
}
for (var i
= 0; i < protos.length; i++)
{
if (protos[i].getAttribute('name') === name) {
p = protos[i].cloneNode(true);
p.setAttribute('name', externproto.getAttribute('name'));
updateExternProtoUrl(p, protoUrl);
break;
}
}
}
//console.log(p);
return p;
}
function updateExternProtoUrl(proto, url)
{
var idx
= url.lastIndexOf('/');
if
(idx === -1)
return;
var baseUrl = url.substr(0,
idx);
var protos
= proto.getElementsByTagName('ExternProtoDeclare');
if
(protos.length === 0) {
protos
= proto.getElementsByTagName('externprotodeclare');
}
for (var i
= 0; i < protos.length; i++)
{
var protoUrl = protos[i].getAttribute('url'),
base = baseUrl;
protoUrl =
protoUrl.replace(/"/g, '');
console.log(protoUrl);
protoUrl
= base.concat(((protoUrl.charAt(0) === '/') ? ''
: '/'), protoUrl);
console.log('Updated externproto
url', protoUrl);
protos[i].setAttribute('url', protoUrl);
}
var inl = proto.getElementsByTagName('inline');
if (inl.length === 0) {
inl = proto.getElementsByTagName('Inline');
}
for
(var i = 0; i <
inl.length; i++) {
var inlUrl
= inl[i].getAttribute('url'), base = baseUrl;
inlUrl = inlUrl.replace(/"/g, '');
console.log(inlUrl);
protoUrl = base.concat(((inlUrl.charAt(0) === '/')
? '' : '/'), inlUrl);
console.log('Updated inline url', inlUrl);
inl[i].setAttribute('url',
inlUrl);
}
}
function loadProto(x3dNode,
proto) {
var
protoI = getProtoInterface(proto);
//najdu v dokumentu reference na objekt
a zacne nahrazovani
protoInstances = x3dNode.getElementsByTagName(protoI.name);
console.log('protoI.name: ' + protoI.name, protoInstances.length +
' instances');
for
(var j = 0; j <
protoInstances.length; j++) {
//console.log(j+" "+protoInstances[j]);
//console.log(j, protoInstances[j]);
var g
= document.createElement('Group');
if (protoInstances[j].hasAttribute("USE") ||
protoInstances[j].hasAttribute("use")) {
g.setAttribute("USE", protoInstances[j].getAttribute("USE"));
protoInstances[j].parentNode.appendChild(g);
continue;
}
var protoVal = prepareRealProtoValues(protoI, protoInstances[j]);
if ('DEF' in protoVal) {
g.setAttribute("DEF", protoVal['DEF']);
}
if ('id' in
protoVal) {
g.setAttribute("id", protoVal['id']);
} else
{
g.setAttribute("id", protoI.name + j);
}
var protoBody = proto.getElementsByTagName('ProtoBody')[0];
//console.log(j, 'body',protoBody);
for (k =
0; k < protoBody.childNodes.length; k++) {
//testuji
zda mam doopravdy X3Dom node
if (protoBody.childNodes[k].nodeType
=== Node.ELEMENT_NODE) {
//console.log(k, protoBody.childNodes[k]);
var
element = protoBody.childNodes[k].cloneNode(true);
replaceProtoValues(element, protoVal);
setNamespace(protoI.name
+ j, element, true);
g.appendChild(element);
}
}
protoInstances[j].parentNode.appendChild(g);
}
//*
while
(protoInstances.length > 0) {
protoInstances[0].parentNode.removeChild(protoInstances[0]);
}//*/
}
//precte zahlavi PROTOtypu
a pripravi si jsObject pro snadnejsi
praci
function getProtoInterface(proto) {
var prI = {}; //protoInterface object
prI.name = proto.getAttribute('name');
protoI = proto.getElementsByTagName('ProtoInterface');
protoIfields = protoI[0].getElementsByTagName('field');
for (var j
= 0; j < protoIfields.length; j++)
{
//POZOR - toLowerCase je
tu proto, ze u instanci jsou
z nejakeho neznameho duvodu jmena atributu
malym pismem - podobne v replaceProtoValues()
var attrName = protoIfields[j].getAttribute("name").toLowerCase();
prI[attrName] = {};
prI[attrName].value =
protoIfields[j].getAttribute("value");
prI[attrName].accessType = protoIfields[j].getAttribute("accessType");
}
//console.log(prI);
return prI;
}
//udela
kopii zahlavi prototypu a zmeny atributy
dle pozadavku instance
function prepareRealProtoValues(protoInterface, instance) {
var prI =
jQuery.extend(true, {}, protoInterface); //hluboka kopie objektu
- vznikla mi tu zavislost na
jquery !
//var
prI = JSON.decode(JSON.encode(protoInterface)); //hluboka kopie objektu
- asi by se melo resit
jinak !
//console.log(prI);
for (var i
= 0; i < instance.attributes.length; i++)
{
//POZOR - instance.attributes[i].name je
z nejakeho neznameho duvodu malymi pismeny,
proto jsou v nekterych funkcich attr.toLowerCase()...
if (instance.attributes[i].name.toUpperCase() === "DEF") {
prI['DEF']
= instance.attributes[i].value;
} else if
(instance.attributes[i].name.toLowerCase() === "id") {
prI['id'] = instance.attributes[i].value;
} else {
prI[instance.attributes[i].name.toLowerCase()].value = instance.attributes[i].value;
}
}
return prI;
}
//nahradi v
elementu atributy definovane pomoci IS a
CONNECT ze ty v jsObjektu zahlaviPrototypu
function
replaceProtoValues(element, protoInterface) {
isElem = element.getElementsByTagName('IS');
if (isElem.length === 0) {
isElem = element.getElementsByTagName('is');
}
//for (var
j = 0; j < isElem.length;
j++) {
while
(isElem.length > 0) {
isElement
= isElem[0];
isParent = isElement.parentNode;
connections = isElement.getElementsByTagName('connect');
for
(var k = 0; k <
connections.length; k++) {
//POZOR - toLowerCase je
tu proto, ze u instanci jsou
z nejakeho neznameho duvodu jmena atributu
malym pismem - podobne v getProtoInterface()
var
fieldName = connections[k].getAttribute('protoField').toLowerCase();
if (protoInterface.hasOwnProperty(fieldName)) { //pro
jistotu si overime, ze ta vlastnost
existuje v zahlavi
isParent.setAttribute(connections[k].getAttribute('nodeField'), protoInterface[fieldName].value);
}
}
isParent.removeChild(isElem[0]);
}
}
if (!Array.forEach) {
Array.forEach = function(array,
fun, thisp) {
var len
= array.length;
for (var i
= 0; i < len; i++)
{
if (i in array) {
fun.call(thisp, array[i], i, array);
}
}
};
}
function
setNamespace(prefix, childDomNode, mapDEFToID) {
if (childDomNode instanceof Element &&
childDomNode.setAttribute !== undefined) {
if
(childDomNode.hasAttribute('id')) {
childDomNode.setAttribute('id', prefix.toString().replace(' ', '') +
'__' + childDomNode.getAttribute('id'));
}
if (childDomNode.hasAttribute('DEF')) {
childDomNode.setAttribute('DEF', prefix.toString().replace(' ', '')
+ '__' + childDomNode.getAttribute('DEF'));
if (mapDEFToID)
{
childDomNode.setAttribute('id', childDomNode.getAttribute('DEF'));
}
} else if (childDomNode.hasAttribute('USE')) {
childDomNode.setAttribute('USE',
prefix.toString().replace(' ', '') + '__' +
childDomNode.getAttribute('USE'));
}
if (childDomNode.localName.toUpperCase()
=== 'ROUTE') {
childDomNode.setAttribute('fromNode',prefix.toString().replace(' ', '') +
'__' + childDomNode.getAttribute('fromNode'));
childDomNode.setAttribute('toNode',prefix.toString().replace(' ', '') +
'__' + childDomNode.getAttribute('toNode'));
}
}
if (childDomNode.hasChildNodes()) {
Array.forEach(childDomNode.childNodes, function(children)
{
setNamespace(prefix, children, mapDEFToID);
});
}
}
function loadX3DScene(dname) {
//var xhttp = new
window.XMLHttpRequest();
if (window.XMLHttpRequest)
{
xhttp = new XMLHttpRequest();
} else {
xhttp = new ActiveXObject("Microsoft.XMLHTTP");
}
/*
xmlhttp.onreadystatechange
= function() {
if (xmlhttp.readyState === 4 &&
xmlhttp.status === 200) {
}
};
*/
if (xhttp.overrideMimeType) {
xhttp.overrideMimeType('text/xml');
}
xhttp.open("GET", dname, false);
xhttp.send();
var inlScene = null, xml
= null;
if
(navigator.appName != "Microsoft Internet Explorer") {
xml = xhttp.responseXML;
}
if
(xml === null) {
xml
= new DOMParser().parseFromString(xhttp.responseText, "text/xml");
}
//console.log(xml,xhttp.responseXML,xhttp.responseText);
if (xml !==
undefined && xml !== null) {
inlScene = xml.getElementsByTagName('Scene')[0] || xml.getElementsByTagName('scene')[0];
}
return inlScene;
}
///extra functions
function getInlinedElement(inName, id)
{
return document.getElementById(inName
+ '__' + id);
}
function info(node, s)
{
//if (node.nodeValue)
if (node ===
null)
return;
var n = node.childNodes;//getElementsByTagName("*");
console.log(n.length, node.nodeName, node.parentNode.nodeName);
for (var i = 0;
i < n.length; i++) {
console.log(s, n[i].nodeName, n[i].nodeValue);
info(n[i], '
' + s);
//if (n[i].hasAttributes('id'))
console.log(" ",n[i].getAttribute('id'));
}
}
Zapisuje události do logu během zobrazování scény.
<script type="text/javascript">
var
bg;
document.onload = function() {
var counter
= 0;
document.getElementById('inID').addEventListener('load',function(ev)
{
//info(this);
counter++;
console.log(counter,"inline onload start");
if (counter
=== 1) {
//copy children of inline
to parent of inline
var el;
for (k
= 0; k < this.childNodes.length; k++)
{
//console.log(this.childNodes[k],this.childNodes[k].localName);
el = this.childNodes[k].cloneNode(true);
if (el.localName.toLowerCase() === 'background')
{
bg = el;
el.setAttribute('set_bind','true');
} else
this.parentNode.appendChild(el);
}
// removes children from inline
//
this.setAttribute('url','');
console.log("process protos", counter);
processProtos(this.parentNode);
console.log(ev,this.nodeName,this.childNodes.length);
//this.parentNode.removeChild(this);
init();
console.log("protos loaded",
counter);
} else {
console.log(this.nodeName,this.childNodes.length);
}
console.log(counter,"inline onload end");
});
//
return false;
};
</script>