HTML preprocessors can make writing HTML more powerful or convenient. For instance, Markdown is designed to be easier to write and read for text documents and you could write a loop in Pug.
In CodePen, whatever you write in the HTML editor is what goes within the <body>
tags in a basic HTML5 template. So you don't have access to higher-up elements like the <html>
tag. If you want to add classes there that can affect the whole document, this is the place to do it.
In CodePen, whatever you write in the HTML editor is what goes within the <body>
tags in a basic HTML5 template. If you need things in the <head>
of the document, put that code here.
The resource you are linking to is using the 'http' protocol, which may not work when the browser is using https.
CSS preprocessors help make authoring CSS easier. All of them offer things like variables and mixins to provide convenient abstractions.
It's a common practice to apply CSS to a page that styles elements such that they are consistent across all browsers. We offer two of the most popular choices: normalize.css and a reset. Or, choose Neither and nothing will be applied.
To get the best cross-browser support, it is a common practice to apply vendor prefixes to CSS properties and values that require them to work. For instance -webkit-
or -moz-
.
We offer two popular choices: Autoprefixer (which processes your CSS server-side) and -prefix-free (which applies prefixes via a script, client-side).
Any URLs added here will be added as <link>
s in order, and before the CSS in the editor. You can use the CSS from another Pen by using its URL and the proper URL extension.
You can apply CSS to your Pen from any stylesheet on the web. Just put a URL to it here and we'll apply it, in the order you have them, before the CSS in the Pen itself.
You can also link to another Pen here (use the .css
URL Extension) and we'll pull the CSS from that Pen and include it. If it's using a matching preprocessor, use the appropriate URL Extension and we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
JavaScript preprocessors can help make authoring JavaScript easier and more convenient.
Babel includes JSX processing.
Any URL's added here will be added as <script>
s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.
You can apply a script from anywhere on the web to your Pen. Just put a URL to it here and we'll add it, in the order you have them, before the JavaScript in the Pen itself.
If the script you link to has the file extension of a preprocessor, we'll attempt to process it before applying.
You can also link to another Pen here, and we'll pull the JavaScript from that Pen and include it. If it's using a matching preprocessor, we'll combine the code before preprocessing, so you can use the linked Pen as a true dependency.
Search for and use JavaScript packages from npm here. By selecting a package, an import
statement will be added to the top of the JavaScript editor for this package.
Using packages here is powered by esm.sh, which makes packages from npm not only available on a CDN, but prepares them for native JavaScript ESM usage.
All packages are different, so refer to their docs for how they work.
If you're using React / ReactDOM, make sure to turn on Babel for the JSX processing.
If active, Pens will autosave every 30 seconds after being saved once.
If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.
If enabled, your code will be formatted when you actively save your Pen. Note: your code becomes un-folded during formatting.
Visit your global Editor Settings.
<canvas id="c" style="width:100%;height:100%;"></canvas>
<div id="clock"></div>
<script id="2d-vertex-shader" type="x-shader/x-vertex">
//proc 3d DOC {violet bold}
//
// 3d coordinate system used on sebastian.it
//
//
// +Y
// |
// e |
// n |
// a | XY - plane
// l |
// p |
// / |
// ZY /------------------+X
// /
// / ZX - plane
// /
// +Z
// In our world all graphic objects are represented by a quadrilateral polygon.
// Each polygon is composed of two triangles and therefore has 6 vertices (a, b, c; d, e, f).
// Each vertex is composed of three X,Y,Z coordinates (aX,aY,aZ, bX,bY,bZ ... fX,fY,fZ).
//
// a d e
// |\ ------
// | \ \ |
// | \ \ |
// | \ \ |
// ------ \|
// b c f
//
// Each polygon has a texture assigned to the vertices of the triangles that compose it.
// Since the texture has no depth it has only two coordinates per vertex.
//
// In our simplified 3d world there are two types of geometric objects:
// - the tiles "T", which make up the terrain of the world and are considered fixed.
// - the entities "E", which represent everything else and which are generally dynamic objects.
//
// NOTE
// A graphical feature that differentiates between tiles and entities
// is the method by which they are drawn. The tiles do not have any kind of
// transparency while the entities do.
// This distinction has a weight in webgl since it forces us to
// manually manage the z-order when we draw objects that need alpha-blending
// as it is necessary to disable the depth buffer by using the following statement
// gl.depthMask (false)
// The tiles make up the ground and are drawn parallel to the ZX plane,
// entities are generally drawn parallel to the XY plane except in some cases.
// For example, the following entities are drawn parallel to the ZX plane:
// - water
// - nymphaea
//
// Here is an "excellent" representation of what has been said:
// ._____.
// | |
// ------ | E |
// / T / |_____|
// /_____/
//
//
// TEXTURES
// ref: https://open.gl/textures
//
// The coordinates of the textures follow the opengl logic
// in which the coordinates are normalized in the range 0.0-1.0
//
// The pixels in the texture are addressed using texture coordinates
// during drawing operations.
// 0,0 is conventionally the bottom-left corner
// 1,1 is the top-right corner of the texture image
//
//
// 0.0 1.0 1.0 1.0
// .______________.
// | |
// | |
// | |
// | |
// | |
// | |
// |______________|
// 0.0 0.0 1.0 0.0
//
//
// To avoid confusion with the X,Y coordinates of the vertices,
// by convention the coordinates of the textures are referenced
// with the parameters S and T.
//
// This is how the polygons are represented in our code:
// Tile "T" - ZX plane
// Since the texture follows the order of the vertices of the triangles
// we arrange the coordinates S and T according to the current vertex:
//
// vertices name buffer_index texture_coords name
// X Y Z S T
// 0.0 0.0 0.0 a 0, 1, 2 0.0 1.0 A
// 0.0 0.0 1.0 b 3, 4, 5 0.0 0.0 B
// 1.0 0.0 1.0 c 6, 7, 8 1.0 0.0 C
//
// 0.0 0.0 0.0 d 9,10,11 0.0 1.0 D
// 1.0 0.0 0.0 e 12,13,14 1.0 1.0 E
// 1.0 0.0 1.0 f 15,16,17 1.0 0.0 F
//
//
// +Y
// |
// e |
// n |
// a |
// l |
// p |
// / |
// ZY aA,dD---------eE----+X
// /\ /
// / \ /
// / \ /
// / \ /
// / \ /
// /__________\/
// /bB cC,fF
// /
// +Z
//
//
//entity "E" - XY plane
//
// vertices name buffer_index texture_coords name
// X Y Z S T
// 0.0 1.0 0.0 a 0, 1, 2 0.0 1.0 A
// 0.0 0.0 0.0 b 3, 4, 5 0.0 0.0 B
// 1.0 0.0 0.0 c 6, 7, 8 1.0 0.0 C
//
// 0.0 1.0 0.0 d 9,10,11 0.0 1.0 D
// 1.0 1.0 0.0 e 12,13,14 1.0 1.0 E
// 1.0 0.0 0.0 f 15,16,17 1.0 0.0 F
//
//
// +Y
// |
// aA,dD--------eE
// |\ |
// | \ |
// | \ |
// | \ |
// | \ |
// e | \ |
// n | \ |
// a | \ |
// l | \ |
// p | \ |
// / | \|
// ZY bB,dD--------cC,fF-----+X
// /
// /
// /
// /
// /
// +Z
//
//
// and I would say that for today I have done enough ASCII art.
//
//
//
//--------------------------------------------------------------------------
//For our simple world lowp precision is enough
precision lowp float;
precision lowp int;
// vertex shader inputs:
attribute vec3 aVertexPosition; //these are the coordinates of the vertices -> x,y,z
attribute vec2 aTextureCoord; //s,t textures coords for each vertext
attribute vec3 aEntityTranslation; //x,y,z translations are applied to each vertex to move entities around the world (Daft Punk)
attribute vec4 aEntityColor; //r,g,b,a colors for every vertex
attribute vec4 aEntityProperties;
// [0]=entity current texture normalized x0 coordinate (used for x fliping)
// [1]=texture_atlas_layer_index
// [2]=entity current texture normalized x1 coordinate (used for x fliping)
// since apparently openl gl 3.0 is required for bitwise operations ....
// [3]=poor man's fast bitwise -> 'packed' combined mutual exclusive properties
// bool hasShadowMitigation (generally clouds and other types of objects in the sky)
// bool isLightEmitter (sun, moon)
// bool isFlippedX (flip entity around y axis)
uniform mat4 uMVMatrix; //model view matrix -> rotations
uniform mat4 uPMatrix; //camera projection matrix -> perspective
uniform vec3 uCameraTranslation; //the x, y, z coordinates of the camera are added to each vertex
uniform vec3 uPointLighting1Location; //the x,y,z position of our first light point
uniform vec3 uPointLighting2Location; //the x,y,z position of our second light point
// global ambient light
// setting it to 1.0.1.0.1.0 we have full lighting
// setting it to 0.0.0.0.0.0 will have light only from the point light
uniform lowp vec3 uAmbientLightColorIntensity;
uniform lowp vec3 uAmbientLightColor; //the color of the ambient light, controls the color of all sprites globally
varying vec2 vTextureCoord;
varying vec3 vLightWeighting;
varying vec3 vLightWeightingWhiteLight;
varying float vTextureAlpha;
varying float vTextureLayerIndex;
void main(void){
vec3 pointLighting1ColorIntensity=vec3(1.0,1.0,1.0);//light color intensity of point light 1 (sun)
vec3 pointLighting2ColorIntensity=vec3(0.5,0.5,0.6);//light color intensity of point light 2 (moon) a little bluish
gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition+aEntityTranslation-uCameraTranslation,1.0);
vTextureCoord = aTextureCoord;
vTextureAlpha =aEntityColor.a;
vTextureLayerIndex =aEntityProperties[1];
float combinedProperties=aEntityProperties[3];
//1
bool hasShadowMitigation=((combinedProperties>0.9 && combinedProperties<1.9)); //clouds
//10
bool isLightEmitter =(combinedProperties>9.9 && combinedProperties<10.9); //stars and satellites
//20
bool isFlippedX =(combinedProperties>19.9); //entities
if (isFlippedX){
//aEntityProperties receives at aEntityProperties[0]
//the normalized x coordinate of the texture from the texture atlas
//and aEntityProperties[0] the normalized x1 coordinates (x + width) of the texture
vTextureCoord.x = aEntityProperties[2]-aTextureCoord.x+aEntityProperties[0];
}
vec3 pointLighting1Location=uPointLighting1Location;
vec3 pointLighting2Location=uPointLighting2Location;
if (hasShadowMitigation){
//Let's raise the light for the current entity more than the rest,
//this allows us to have illuminated objects on the sky while the others are not
pointLighting1Location[1]+=100.0; //sun light
pointLighting2Location[1]+=20.0; //moon light
}
if (!isLightEmitter){
//the entity does not emit its own light
//we must determine the direction of the light:
vec3 vectorNormal=vec3(0.0,1.0,0.0); //in our simple geometry just consider a fixed normal
vec3 light1Direction = normalize(pointLighting1Location - aEntityTranslation - aVertexPosition);
vec3 light2Direction = normalize(pointLighting2Location - aEntityTranslation - aVertexPosition);
float directionalLight1Weighting = max(dot(vectorNormal, light1Direction), 0.0);
float directionalLight2Weighting = max(dot(vectorNormal, light2Direction), 0.0);
vec3 sunWhiteLight = pointLighting1ColorIntensity
* directionalLight1Weighting * (uAmbientLightColor+0.1);
//+0.1 explained ->
//give a little shove to the color to have white <-> #fffff during zenith
vec3 moonWhiteLight = pointLighting2ColorIntensity
* directionalLight2Weighting * uAmbientLightColor;
//our world has two mobile points of light in total
vLightWeighting = uAmbientLightColorIntensity + sunWhiteLight * aEntityColor.xyz; //sunlight
vLightWeighting+= uAmbientLightColorIntensity + moonWhiteLight * aEntityColor.xyz; //moonlight
//----
//we repeat the above calculations but without taking into
//account the color of the entity. This will give us a white
//light that we can use to manage the 'neutral' pixels of
//the entity in the fragment shader that will not have
//to undergo color alterations (such as the eyes).
vLightWeightingWhiteLight = uAmbientLightColorIntensity + sunWhiteLight;
vLightWeightingWhiteLight+= uAmbientLightColorIntensity + moonWhiteLight;
}else{
//if the entity emits light do not apply color variation
vLightWeighting=vec3(1.0,1.0,1.0);
}
}
</script>
<script id="2d-fragment-shader" type="x-shader/x-fragment">
precision lowp float;
precision lowp int;
//our textures
//instead of using a texture array that requires an extension
//we select the texture atlas layer by using a variable.
//It is not the most efficient thing in the world but it works
//and for our little world is enough.
//about tiling+texture atlas
//----
//the texture bleeding phenomenon is 'solved'
//by an appropriate drawing method during the texture atlas generation
uniform sampler2D uTextureSampler0; //ref: https://www.khronos.org/opengl/wiki/Sampler_(GLSL)
uniform sampler2D uTextureSampler1;
uniform sampler2D uTextureSampler2;
uniform sampler2D uTextureSampler3;
uniform sampler2D uTextureSampler4;
uniform sampler2D uTextureSampler5;
uniform sampler2D uTextureSampler6;
uniform sampler2D uTextureSampler7;
//2018-04-02 15:54:41 - in the tests I did on mobile it seems that there are problems beyond the 8 textures
//the texCoords passed in from the vertex shader.
//gluniform doc -> ref: https://www.khronos.org/registry/OpenGL-Refpages/gl4/html/glUniform.xhtml
varying vec2 vTextureCoord;
varying vec3 vLightWeighting;
varying vec3 vLightWeightingWhiteLight;
varying float vTextureAlpha;
varying float vTextureLayerIndex;
void main(void){
vec4 color;
// We use a float range to determine the layer
// and not a specific number to allow correct management on mobile browsers
if (vTextureLayerIndex==0.0) //select atlas 0
color=texture2D(uTextureSampler0,vec2(vTextureCoord.s,vTextureCoord.t));
else if (vTextureLayerIndex>0.9 && vTextureLayerIndex<1.9) //atlas 1
color=texture2D(uTextureSampler1,vec2(vTextureCoord.s,vTextureCoord.t));
else if (vTextureLayerIndex>1.9 && vTextureLayerIndex<2.9) //atlas 2
color=texture2D(uTextureSampler2,vec2(vTextureCoord.s,vTextureCoord.t));
else if (vTextureLayerIndex>2.9 && vTextureLayerIndex<3.9) //atlas 3
color=texture2D(uTextureSampler3,vec2(vTextureCoord.s,vTextureCoord.t));
else if (vTextureLayerIndex>3.9 && vTextureLayerIndex<4.9) //atlas 4
color=texture2D(uTextureSampler4,vec2(vTextureCoord.s,vTextureCoord.t));
else if (vTextureLayerIndex>4.9 && vTextureLayerIndex<5.9) //atlas 5
color=texture2D(uTextureSampler5,vec2(vTextureCoord.s,vTextureCoord.t));
else if (vTextureLayerIndex>5.9 && vTextureLayerIndex<6.9) //atlas 6
color=texture2D(uTextureSampler6,vec2(vTextureCoord.s,vTextureCoord.t));
else if (vTextureLayerIndex>6.9 && vTextureLayerIndex<7.9) //atlas 7
color=texture2D(uTextureSampler7,vec2(vTextureCoord.s,vTextureCoord.t));
//2018-05-04 15:39:04
//with the following IF we choose the RED color (used as a mask) in a fairly aprox way,
// We use a color mask to be able to color the eyes of the entities with white light
// and the rest of the body with the color of the sprite
if (color.r>.5 && color.g<.5 && color.b<.5){
float gray=color.r+color.g+color.b/3.0;
vec3 colorGray=vec3(gray,gray,gray);
gl_FragColor = vec4(colorGray.rgb*vLightWeightingWhiteLight,vTextureAlpha*color.a);
}else{
gl_FragColor = vec4(color.rgb*vLightWeighting,vTextureAlpha*color.a);
}
}
</script>
html, body{
margin:0;
padding:0;
width:100%;
height:100%;
overflow:hidden;
}
#clock{
font-family:"Lucida Sans Unicode", "Lucida Grande", sans-serif;
position:absolute;
font-size:40px;
color:white;
bottom:10px;
right:25px;
}
const SEBASTIAN={ //proc SEBASTIAN
GLOBALS:{ //proc GLOBALS {orange indent_1}
fps:30, //orginal value: 1000 - number of frames rendered per second, the higher the number the greater the cpu usage
maxHandledTextures:8, //8 seems the max number suitable for mobile. if increased, fragment shader code modifications are required iON2D2Js0y
maxTextureAtlasWidth:4096, //4096 tested on on iPhone 6 and Android
maxTextureAtlasHeight:4096,
m3d:null, //mouse 3d coordinates from 2d position
mx:0, //actual mouse coord and prev mouse coords
my:0,
mb:null, //mouse button pressed or released
oMx:null, //detect mouse movement
oMy:null,
//time
hours:null,
minutes:null,
//entities idx counter
idx:0,
loadedAssets:0, //texture loader index
//pressed keys
keys:[],
keysUp:[],
//frame control
lastTime:window.performance.now(),
//color mapping and time travel
lastTimeKey:null,
debugLightColors:1,
timeTravel:0,
//map Editor
tilesColorPool:['C5','C1','C3','C2','C4','B1','B2','B3'],
tilesColorPoolIdx:0,
tilesBusyList:{},
//tile blob editor
mapEntityGroups:[
'nymphaea','pavementAngleTopLeft','pavementTop','pavementAngleTopRight',
'pavementLeft','pavementRight',
'pavementAngleBottomLeft','pavementBottom','pavementAngleBottomRight',
'water','water_tiled','grass','taraxacum','bullrushes','frog',
],
mapEntityGroupsIdx:0,
//--
editorMode:'terrain', //auto select editor mode
currentInput:null,
currentEntityId:0, //current selected entity
currentEntityMOId:0, //current entity under mouse
entitySelectionColor:[1.0,0.0,1.0], //the color used to highlight a selected entity
entitySelectedColor:[1.0,0.0,1.0], //the color used to highlight an entity when the mouse is on it
tilesTexturePool:['pavement_02','pavement_01'],
tilesTexturePoolIdx:0,
tilesOpacityPool:[1.0,.7,.9,.5,.3],
tilesOpacityPoolIdx:0,
currentTileId:null, //current selected tile
currentTileMOId:null, //current tile under mouse
dynamicEntitiesGeometry:1,
//flags/counters
isWorldTilesVerticesPositionDirty:0,
isWorldTilesColorsDirty:0,
isWorldTilesTextureCoordsDirty:0,
isWorldTilesPropertiesDirty:0, //if a tile alpha or sprite is changed we set this flag to 1
autoBuildTextureAtlases:0, //if true, load all the separate texture images and create a texture atlas, otherwise load the atlas (manually saved)
isEditorEnabled:0,
loadSavedScene:1,
isMouseDirty:0, //used to perform analysis only during mouse movements
sceneVersion:0, //used to visually increase the version number of the scene during save, it has no other uses.
useUTCTime:1,
},
init:function(){ //proc init {green indent_1}
SEBASTIAN.GLOBALS.canvas=document.getElementById('c');
SEBASTIAN.GLOBALS.clock=document.getElementById('clock');
SEBASTIAN.WEBGL.initGL();
SEBASTIAN.UTILS.init();
SEBASTIAN.WEBGL.initShaders();
SEBASTIAN.WEBGL.WORLD.ENTITIES.init();
//init time
// we use getUTCHours so that there are no 'jumps'
// in the hour due to the introduction of daylight savings time
// if we used eg getHours
// there would be a jump from 01:59 to 03:00 on 24/03/2018
// and this would cause the moon to jump forward
var tDate=new Date();
SEBASTIAN.GLOBALS.fpsInterval=1000/SEBASTIAN.GLOBALS.fps;
if (SEBASTIAN.GLOBALS.useUTCTime){
SEBASTIAN.GLOBALS.hours=tDate.getUTCHours();
SEBASTIAN.GLOBALS.minutes=tDate.getUTCMinutes();
}else{
SEBASTIAN.GLOBALS.hours=tDate.getHours();
SEBASTIAN.GLOBALS.minutes=tDate.getMinutes();
}
//proc assets loading CODEPEN {violet indent_2}
//load assets with a callback, then load world with a callback
//then init gameloop.
SEBASTIAN.WEBGL.GLOBALS.textures=textureData_js;
SEBASTIAN.GLOBALS.lightColorTimeMap=colormap_js;
var o=SEBASTIAN.GLOBALS.lightColorTimeMap;
var counter=0;
// assign an index to every hour of the day,
// we will use this to rotate the moon and the sun
// based on current hour
for (var z in o){
o[z].idx=counter;
//console.log(z);
counter++;
}
var assetsListAtlases=[
{'atlas1.glTexture':atlas_js}, //here we can for example choose textures with different quality/resolution to improve performance on mobile browsers
]
var assetsList=[];
assetsList=assetsListAtlases;
SEBASTIAN.UTILS.initAssets(assetsList,function(){
SEBASTIAN.WEBGL.loadTextureAtlases(function(){
SEBASTIAN.WEBGL.WORLD.init();
//SEBASTIAN.WEBGL.WORLD.load();
SEBASTIAN.WEBGL.WORLD.onloadHandler(
scene_js,
function(){SEBASTIAN.gameLoop(window.performance.now())}
)
});
});
},
gameLoop:function(newtime){ //proc gameLoop {green indent_1}
const _seba=SEBASTIAN;
//proc draw scene call {violet indent_2}
_seba.WEBGL.WORLD.draw(newtime);
requestAnimationFrame(_seba.gameLoop); //loop forever
},
UTILS:{ //proc UTILS {orange indent_1}
init:function(){ //proc init {green indent_2}
const _seba=SEBASTIAN;
//proc window.onresize {violet indent_3}
window.onresize=function(){
//console.log('resize',document.documentElement.clientWidth);
//canvas resizing
var docWidth=document.documentElement.clientWidth;
var docHeight=document.documentElement.clientHeight;
var canvasDom=document.getElementById('c');
c.width=docWidth;
c.setAttribute('width',docWidth);
c.style.width=docWidth+'px';
c.height=docHeight;
c.style.height=docHeight+'px';
c.setAttribute('height',docHeight);
//resize webgl render window
var gl=_seba.GLOBALS.webgl_ctx; //lookup var
gl.viewportWidth=c.width;
gl.viewportHeight=c.height;
_seba.WEBGL.WORLD.GLOBALS.isViewportDirty=1;
};
window.onresize();
},
onVisibilityChangeHandler:function(hiddenPropertyName){ //proc editorInputKeyUp
if (document[hiddenPropertyName]){
SEBASTIAN.GLOBALS.fpsInterval=10000;
console.log('HIDDEN',new Date());
}else{
SEBASTIAN.GLOBALS.fpsInterval=1000/SEBASTIAN.GLOBALS.fps;
console.log('VISIBLE',new Date());
}
},
applyTimeCalc(cfg){ //proc applyTimeCalc {green indent_2}
var config={
//sunLightVerticalPosition:cfg.sunLightVerticalPosition, //_seba.WEBGL.WORLD.GLOBALS.sunLightVerticalDistance
parameter:cfg.parameter,
currentHour:cfg.currentHour,
currentMinute:cfg.currentMinute,
fromHours:cfg.fromHours,
toHours:cfg.toHours,
fromMinutes:cfg.fromMinutes,
toMinutes:cfg.toMinutes,
fromValue:cfg.fromValue,
toValue:cfg.toValue,
logInfo:cfg.logInfo || 0,
applyTimeBouncing:cfg.applyTimeBouncing,
}
var _seba=SEBASTIAN;
var parameter=config.parameter;
var currentHour=config.currentHour;
var currentMinute=config.currentMinute;
var fromHours=config.fromHours;
var toHours=config.toHours;
var fromMinutes=config.fromMinutes;
var toMinutes=config.toMinutes;
var fromValue=config.fromValue;
var toValue=config.toValue;
var logInfo=config.logInfo;
var applyTimeBouncing=config.applyTimeBouncing;
if (typeof applyTimeBouncing==='undefined')
applyTimeBouncing=1;
//build Time index
var h_key, m_key, colorKey;
//current index
//to index
h_key=currentHour;
m_key=currentMinute;
colorKey=h_key+'_'+m_key;
var currentTimeIdx=SEBASTIAN.GLOBALS.lightColorTimeMap[colorKey].idx;
//from index
h_key=fromHours;
m_key=fromMinutes;
colorKey=h_key+'_'+m_key;
var initTimeIdx=SEBASTIAN.GLOBALS.lightColorTimeMap[colorKey].idx;
//to index
h_key=toHours;
m_key=toMinutes;
colorKey=h_key+'_'+m_key;
var endTimeIdx=SEBASTIAN.GLOBALS.lightColorTimeMap[colorKey].idx;
var distanceIdx=endTimeIdx-initTimeIdx;
var halfTimeIdx=initTimeIdx+(distanceIdx)/2;
if (applyTimeBouncing){
//if (currentHour===fromHours && currentMinute>=fromMinutes){
if (currentTimeIdx>=initTimeIdx && currentTimeIdx<halfTimeIdx){
//console.log('+delta',(currentTimeIdx-initTimeIdx)*1/halfTimeIdx);
//var delta=(currentTimeIdx-initTimeIdx)/initTimeIdx; //normalize
var delta=(currentTimeIdx-initTimeIdx)*1/distanceIdx*2; //normalize to 0..1
parameter=fromValue*(1-delta)+toValue*delta; //lerp
//console.log('>>',parameter);
}
if (currentTimeIdx>=halfTimeIdx && currentTimeIdx<=endTimeIdx){
//var delta=1-((toMinutes-currentMinute)/toMinutes); //normalize
//console.log('-delta',1-((endTimeIdx-currentTimeIdx)*1/halfTimeIdx));
//var delta=1-((endTimeIdx-currentTimeIdx)/endTimeIdx); //normalize
var delta=1-((endTimeIdx-currentTimeIdx)*1/distanceIdx*2);
parameter=toValue*(1-delta)+fromValue*delta; //lerp
//console.log('<<',parameter);
}
}else{
if (currentTimeIdx>=initTimeIdx && currentTimeIdx<=endTimeIdx){
//console.log('+DELTA',(currentTimeIdx-initTimeIdx)*1/halfTimeIdx);
//var delta=(currentTimeIdx-initTimeIdx)/initTimeIdx; //normalize
var delta=(currentTimeIdx-initTimeIdx)*1/distanceIdx; //normalize to 0..1
parameter=fromValue*(1-delta)+toValue*delta; //lerp
//console.log('>>',parameter);
}
}
return parameter;
},
degToRad(degrees){ //proc deg2rad {green indent_2}
return degrees*Math.PI/180;
},
initAssets:function(tList,callback){ //proc initAssets {green indent_2}
var gl=SEBASTIAN.GLOBALS.webgl_ctx; //lookup var
for (var z=0,zEnd=tList.length;z<zEnd;z++){
//a bit hacky
//for (var assetId in tList[z]){}
//clearer ->
var assetId=Object.keys(tList[z])[0];
if (tList[z][assetId].match(/\.json$/)){
var assetUrl=tList[z][assetId];
var xhr=new XMLHttpRequest();
xhr.onload=function(z,assetId){
return function(){ //func factory {indent_4}
if (xhr.status===200){
var responseText=this.responseText;
if (typeof tList[z].onLoad!=='undefined')
responseText=tList[z].onLoad(responseText);
SEBASTIAN.GLOBALS[assetId]=JSON.parse(responseText); //save the object in SEBASTIAN.GLOBALS with the specified key
if (typeof tList[z].onLoadDone!=='undefined')
responseText=tList[z].onLoadDone(SEBASTIAN.GLOBALS[assetId]);
}else{
//request failed
}
SEBASTIAN.GLOBALS.loadedAssets++;
if (SEBASTIAN.GLOBALS.loadedAssets===tList.length){ //all loaded
callback();
}
}
}(z,assetId);
xhr.open('GET',assetUrl);
xhr.send();
}else if(assetId.match(/\.glTexture$/)){
var imgUrl=tList[z][assetId];
var tempImage=gl.createTexture();
tempImage.image=new Image();
SEBASTIAN.WEBGL.GLOBALS.tempTextures[assetId]=tempImage;
tempImage._data=tList[z].data; //set data
tempImage.image.onload=function(assetId){
return function(){
SEBASTIAN.GLOBALS.loadedAssets++;
//console.log(SEBASTIAN.GLOBALS.loadedAssets,tList.length);
if (SEBASTIAN.GLOBALS.loadedAssets===tList.length){ //all loaded
callback();
}
}
}(assetId);
tempImage.image.src=imgUrl;
}else{
var imgUrl=tList[z][assetId];
var tempImage=new Image();
SEBASTIAN.WEBGL.GLOBALS.tempTextures[assetId]=tempImage;
tempImage._data=tList[z].data; //set data
tempImage.onload=function(assetId){
return function(){
SEBASTIAN.GLOBALS.loadedAssets++;
if (SEBASTIAN.GLOBALS.loadedAssets===tList.length){ //all loaded
callback();
}
}
}(assetId);
tempImage.src=imgUrl;
}
}
},
},
WEBGL:{ //proc WEBGL {orange indent_1}
GLOBALS:{ //proc WEBGL.GLOBALS {orange indent_3}
buffers:{}, //proc buffers {blue indent_3}
textures:{}, //proc textures {blue indent_3} texture database in relation to the atlas texture
tempTextures:{}, //proc tempTextures {blue indent_3} textures loaded individually before creating the atlas texture
shaderProgram:{}, //proc shaderProgram {blue indent_3}
anisotropicFilter:null,
},
//--
initGL:function(){ //proc initGL {green indent_2}
var canvas=SEBASTIAN.GLOBALS.canvas;
//preserveDrawingBuffer -> determines whether or not to clear the buffer at each frame
//alpha:false -> disabled alpha blending with html background
//premultipliedAlpha:false -> blend alpha from gl with html background
SEBASTIAN.GLOBALS.webgl_ctx=canvas.getContext('webgl',{preserveDrawingBuffer:false,premultipliedAlpha:true});
if (!SEBASTIAN.GLOBALS.webgl_ctx) //no luck? ok, let's try something different....
SEBASTIAN.GLOBALS.webgl_ctx=canvas.getContext('experimental-webgl',{preserveDrawingBuffer:false,premultipliedAlpha:true});
//--
var gl=SEBASTIAN.GLOBALS.webgl_ctx; //lookup var
gl.viewportWidth=canvas.width;
gl.viewportHeight=canvas.height;
//enable ALPHA blending for png transparent textures
//gl.blendFunc(gl.SRC_ALPHA,gl.ONE_MINUS_SRC_ALPHA); //premultipliedAlpha should be set to true and -> gl.pixelStorei (gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, true); should be used
//enable ALPHA blending for gif transparent textures (deal with 1 bit transparency)
gl.blendFuncSeparate(gl.SRC_ALPHA, gl.ONE_MINUS_SRC_ALPHA, gl.ONE, gl.ONE_MINUS_SRC_ALPHA);
gl.enable(gl.BLEND);
//2018-03-12 22:58:42
//test if we can enable anisotropic filtering
//https://developer.mozilla.org/en-US/docs/Web/API/EXT_texture_filter_anisotropic
SEBASTIAN.WEBGL.GLOBALS.anisotropicFilter=gl.getExtension('EXT_texture_filter_anisotropic');
// if we want alpha blending for our .PNGs file we can't use DEPTH_TEST
// we manage the depth test in a distinct way during drawing.
// use depthMask(true) for objects without alpha
// use depthMask(false) for transparent objects ->
// in this case the z-ordering must be done by our routine
// see drawloop
gl.enable(gl.DEPTH_TEST);
},
initShaders:function(){ //proc initShaders {green indent_2}
var gl=SEBASTIAN.GLOBALS.webgl_ctx; //lookup var
//Init shaders
//setup a GLSL program
var vertexShader =SEBASTIAN.WEBGL.createShaderFromScript(gl,'2d-vertex-shader');
var fragmentShader=SEBASTIAN.WEBGL.createShaderFromScript(gl,'2d-fragment-shader');
var shaderProgram =SEBASTIAN.WEBGL.createProgram(gl,[vertexShader,fragmentShader]);
SEBASTIAN.WEBGL.GLOBALS.shaderProgram=shaderProgram;
gl.useProgram(shaderProgram);
//proc shaderProgram set vars {violet indent_3}
//set attributes and uniforms parameters
shaderProgram.aVertexPosition_var=gl.getAttribLocation(shaderProgram,'aVertexPosition');
gl.enableVertexAttribArray(shaderProgram.aVertexPosition_var);
//--
shaderProgram.aTextureCoord_var=gl.getAttribLocation(shaderProgram,'aTextureCoord');
gl.enableVertexAttribArray(shaderProgram.aTextureCoord_var);
//--
shaderProgram.aEntityTranslation_var=gl.getAttribLocation(shaderProgram,'aEntityTranslation');
gl.enableVertexAttribArray(shaderProgram.aEntityTranslation_var);
//--
shaderProgram.aEntityColor_var=gl.getAttribLocation(shaderProgram,'aEntityColor');
gl.enableVertexAttribArray(shaderProgram.aEntityColor_var);
//--
shaderProgram.aEntityProperties_var=gl.getAttribLocation(shaderProgram,'aEntityProperties');
gl.enableVertexAttribArray(shaderProgram.aEntityProperties_var);
//--
//--
shaderProgram.uPMatrix_var = gl.getUniformLocation(shaderProgram,'uPMatrix');
shaderProgram.uMVMatrix_var = gl.getUniformLocation(shaderProgram,'uMVMatrix');
//do a configurable loop
for (var z=0;z<SEBASTIAN.GLOBALS.maxHandledTextures;z++){
shaderProgram['uTextureSampler'+z+'_var']=gl.getUniformLocation(shaderProgram,'uTextureSampler'+z);
}
shaderProgram.uAmbientLightColor_var = gl.getUniformLocation(shaderProgram,'uAmbientLightColor');
shaderProgram.uAmbientLightColorIntensity_var = gl.getUniformLocation(shaderProgram,'uAmbientLightColorIntensity');
shaderProgram.uCameraTranslation_var = gl.getUniformLocation(shaderProgram,'uCameraTranslation');
shaderProgram.uPointLighting1Location_var = gl.getUniformLocation(shaderProgram, "uPointLighting1Location");
shaderProgram.uPointLighting2Location_var = gl.getUniformLocation(shaderProgram, "uPointLighting2Location");
},
loadTextureAtlases:function(callback){ //proc loadTextureAtlases {green indent_2}
const _seba=SEBASTIAN;
var gl=SEBASTIAN.GLOBALS.webgl_ctx; //lookup var
var atlasLayerIndex=0;
for (var textureSid in _seba.WEBGL.GLOBALS.tempTextures){
var currentTexture=_seba.WEBGL.GLOBALS.tempTextures[textureSid];
SEBASTIAN.WEBGL.handleLoadedTextureAtlasImage(currentTexture,atlasLayerIndex);
//console.log(_seba.WEBGL.GLOBALS.tempTextures,atlasLayerIndex);
atlasLayerIndex++;
}
delete SEBASTIAN.WEBGL.GLOBALS.tempTextures;
callback();
},
handleLoadedTextureAtlasImage:function(texture,layerIdx){ //proc handleLoadedTextureAtlasImage {green indent_2}
//multitextures -> ref: https://webglfundamentals.org/webgl/webgl-2-textures.html
var gl=SEBASTIAN.GLOBALS.webgl_ctx; //lookup var
var shaderProgram=SEBASTIAN.WEBGL.GLOBALS.shaderProgram;
var USE_MIPMAPS=1;
gl.uniform1i (shaderProgram['uTextureSampler'+layerIdx+'_var'],layerIdx);
gl.activeTexture (gl.TEXTURE0+layerIdx);
gl.bindTexture (gl.TEXTURE_2D,texture); //bind once - the atlas texture
gl.texImage2D (gl.TEXTURE_2D,0,gl.RGBA,gl.RGBA,gl.UNSIGNED_BYTE,texture.image);
gl.texParameteri (gl.TEXTURE_2D,gl.TEXTURE_MAG_FILTER, gl.LINEAR);
if (USE_MIPMAPS){
//gl.texParameteri (gl.TEXTURE_2D,gl.TEXTURE_BASE_LEVEL,0);
gl.generateMipmap(gl.TEXTURE_2D);
gl.texParameteri (gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER, gl.LINEAR_MIPMAP_LINEAR);
}else{
gl.texParameteri (gl.TEXTURE_2D,gl.TEXTURE_MIN_FILTER, gl.LINEAR);
}
//2018-03-12 23:04:23
//https://developer.mozilla.org/en-US/docs/Web/API/EXT_texture_filter_anisotropic
//MAX_TEXTURE_MAX_ANISOTROPY_EXT is 16 on my card
if (SEBASTIAN.WEBGL.GLOBALS.anisotropicFilter)
gl.texParameteri(
gl.TEXTURE_2D,
SEBASTIAN.WEBGL.GLOBALS.anisotropicFilter.TEXTURE_MAX_ANISOTROPY_EXT,
gl.getParameter(SEBASTIAN.WEBGL.GLOBALS.anisotropicFilter.MAX_TEXTURE_MAX_ANISOTROPY_EXT)
);
//2018-02-11 16:26:59
//using the 'CLAMP_TO_EDGE' setting we
//avoid the texture bleeding phenomenon visible
//in the edges of the textures that extend throughout
//the width or height of the tile (tileable-type textures)
//Note: 2018-03-11 23:03:15
//since CLAMP_TO_EDGE only applies to the edges of the texture,
//this setting can not solve the texture bleeding problem if we are using
//a texture atlas
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_S, gl.CLAMP_TO_EDGE );
gl.texParameteri(gl.TEXTURE_2D, gl.TEXTURE_WRAP_T, gl.CLAMP_TO_EDGE );
},
createShaderFromScript:function(gl,scriptId){ //proc createShaderFromScript {green indent_2}
var shaderType;
var shaderScript = document.getElementById(scriptId);
if (!shaderScript)
alert("*** Error: script element not found: " + scriptId);
switch(shaderScript.type){
case 'x-shader/x-vertex':
shaderType = gl.VERTEX_SHADER;
break;
case 'x-shader/x-fragment':
shaderType = gl.FRAGMENT_SHADER;
break;
default:
alert('webgl_createShaderFromScript error unkown type')
break;
}
// Create the shader object
var shader = gl.createShader(shaderType);
// Load the shader source
gl.shaderSource(shader,shaderScript.text);
// Compile the shader
gl.compileShader(shader);
// Check the compile status
var compiled = gl.getShaderParameter(shader, gl.COMPILE_STATUS);
if (!compiled) {
// Something went wrong during compilation; get the error
var lastError = gl.getShaderInfoLog(shader);
console.error("*** Error compiling shader '" + shader + "':" + lastError);
gl.deleteShader(shader);
return null;
}
return shader;
},
createProgram:function(gl,shaders){ //proc createProgram {green indent_2}
var program = gl.createProgram();
for (var ii = 0; ii < shaders.length; ++ii) {
gl.attachShader(program,shaders[ii]);
}
gl.linkProgram(program);
// Check the link status
var linked = gl.getProgramParameter(program, gl.LINK_STATUS);
if (!linked) {
// something went wrong with the link
var lastError = gl.getProgramInfoLog (program);
console.error("Error in program linking:" + lastError);
gl.deleteProgram(program);
return null;
}
return program;
},
project:function(x,y,z,xPos,yPos,zPos,eX,eY,eZ,pMatrix,mvMatrix){ //proc project {green indent_2}
//gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition+aEntityTranslation-uCameraTranslation,1.0);
//gl.viewport(0,0,gl.viewportWidth,gl.viewportHeight);
//gl_Position = uPMatrix * uMVMatrix * vec4(aVertexPosition-uCameraTranslation+uEntityTranslation,1.0);
//https://www.khronos.org/registry/OpenGL-Refpages/es2.0/xhtml/glViewport.xml
//https://github.com/hughsk/from-3d-to-2d/blob/master/index.js
var gl=SEBASTIAN.GLOBALS.webgl_ctx; //lookup var
var out=vec4.fromValues(x-xPos+eX,y-yPos+eY,z-zPos+eZ,1.0);
var pMatrixClone=mat4.clone(pMatrix);
mat4.multiply(pMatrixClone,pMatrixClone,mvMatrix);
//transform world to clipping coordinates
vec4.transformMat4(out,out,pMatrixClone);
var screenX=Math.round(((out[0]/out[2]+1)/2.0)*gl.viewportWidth);
var screenY=Math.round(((1-out[1]/out[2])/2.0)*gl.viewportHeight);
//or
//var screenX=Math.round((out[0]/out[2]+1)*(gl.viewportWidth/2)+x);
//var screenY=Math.round((1-out[1]/out[2])*(gl.viewportHeight/2)+y);
return [screenX,screenY];//pMatrix;//cameraTranslation;//[screenX,screenY];
},
WORLD:{ //proc WEBGL.WORLD {orange indent_2}
GLOBALS:{ //proc WEBGL.WORLD.GLOBALS {orange indent_3}
//vertexPositions:null, //store dynamic terrain vertex positions
//worldTilesData:[], //store info for every world tile (e.g textureindex)
isCameraPositionDirty:1, //flag used to decide whether or not it is necessary to update the translation uniforms of the shader
//tile world columns
//these numbers determine the size of the world
columns:45,
rows:25,
//world colors and flags
sunLightVerticalDistance:300, //height of sunlight (point light) relative to the y position of the sun, the greater the distance the greater the amount of radiated light
isPointLightPositionDirty:1,
isAmbientLightDirty:1,
//def 0.0,0.0,0.0 -> ambient light, the scene has a point light (the sun),
//this parameter indicates how bright the scene is in case the point-light does
//not affect what we are watching
//by setting it to 0,0,0 we get colors with greater contrast
ambientLightColorIntensity:[0.0,0.0,0.0], //black
//this color changes according to the time regardless
//of the light intensity. This parameter allows us to specify
//which color is the global light
//(the point light light componente is fixed into the fragment shader for simplicity)
ambientLightColor:[1.0,1.0,1.0], //1,1,1 -> white
//ambientLightColor:[22/255,4/255,2/255], //1,1,1 -> white
//skyLightColor:[254/255,196/255,1/255], //2018-03-17 11:06:14 discontinued
//ambientLightColor:[171/255,60/255,45/255], //1,1,1 -> white
//ambientLightColor:[0.01,0.01,0.01], //1,1,1 -> white
pMatrix:mat4.create(),
mvMatrix:mat4.create(),
},
//dynamic buffers (ummovable objects)
//static world buffers (ummovable objects)
vertexPositionBuffer:{}, //proc vertexPositionBuffer {blue indent_3}
vertexTextureCoordBuffer:{}, //proc vertexTextureCoordBuffer {blue indent_3}
//---
init:function(){ //proc init {green indent_3} WEBGL.WORLD.init
},
setCameraTo:function(cfg){
var config={
xPos:cfg.xPos,
yPos:cfg.yPos,
zPos:cfg.zPos,
pitch:cfg.pitch,
yaw:cfg.yaw,
}
SEBASTIAN.WEBGL.WORLD.GLOBALS.xPos=config.xPos;
SEBASTIAN.WEBGL.WORLD.GLOBALS.yPos=config.yPos;
SEBASTIAN.WEBGL.WORLD.GLOBALS.zPos=config.zPos;
SEBASTIAN.WEBGL.WORLD.GLOBALS.pitch=config.pitch;
SEBASTIAN.WEBGL.WORLD.GLOBALS.yaw=config.yaw;
SEBASTIAN.WEBGL.WORLD.GLOBALS.isCameraPositionDirty=1
},
syncAllTileBuffersData:function(){ //proc syncAllTileBuffersData {green indent_4}
//console.log('synca');
//update the dynamic buffers of all the world tiles
var _seba=SEBASTIAN;
var worldData =_seba.GLOBALS.worldData;
var dWorldTileSpriteColors=_seba.WEBGL.GLOBALS.buffers.worldTileSpriteColors.data;
for (var z=0,zEnd=worldData.world.length;z<zEnd;z++){
var currentWorldTile=worldData.world[z];
var idx4=currentWorldTile.id*6*4; //added alpha component
//console.log(z,idx4);
//vertex colors (4 points per vertex)
dWorldTileSpriteColors[idx4+0]=currentWorldTile.color1[0];
dWorldTileSpriteColors[idx4+1]=currentWorldTile.color1[1];
dWorldTileSpriteColors[idx4+2]=currentWorldTile.color1[2];
dWorldTileSpriteColors[idx4+3]=currentWorldTile.opacity;
dWorldTileSpriteColors[idx4+4]=currentWorldTile.color1[0];
dWorldTileSpriteColors[idx4+5]=currentWorldTile.color1[1];
dWorldTileSpriteColors[idx4+6]=currentWorldTile.color1[2];
dWorldTileSpriteColors[idx4+7]=currentWorldTile.opacity;
dWorldTileSpriteColors[idx4+8]=currentWorldTile.color1[0];
dWorldTileSpriteColors[idx4+9]=currentWorldTile.color1[1];
dWorldTileSpriteColors[idx4+10]=currentWorldTile.color1[2];
dWorldTileSpriteColors[idx4+11]=currentWorldTile.opacity;
dWorldTileSpriteColors[idx4+12]=currentWorldTile.color1[0];
dWorldTileSpriteColors[idx4+13]=currentWorldTile.color1[1];
dWorldTileSpriteColors[idx4+14]=currentWorldTile.color1[2];
dWorldTileSpriteColors[idx4+15]=currentWorldTile.opacity;
dWorldTileSpriteColors[idx4+16]=currentWorldTile.color1[0];
dWorldTileSpriteColors[idx4+17]=currentWorldTile.color1[1];
dWorldTileSpriteColors[idx4+18]=currentWorldTile.color1[2];
dWorldTileSpriteColors[idx4+19]=currentWorldTile.opacity;
dWorldTileSpriteColors[idx4+20]=currentWorldTile.color1[0];
dWorldTileSpriteColors[idx4+21]=currentWorldTile.color1[1];
dWorldTileSpriteColors[idx4+22]=currentWorldTile.color1[2];
dWorldTileSpriteColors[idx4+23]=currentWorldTile.opacity;
}
//update the buffer only if necessary
_seba.GLOBALS.isWorldTilesColorsDirty=1;
},
syncTileBuffersData:function(currentWorldTile){ //proc syncTileBuffersData {green indent_4}
//console.log('syncb');
//update the dynamic buffers of the world tiles
//console.log('xxx',currentWorldTile.id);
var _seba=SEBASTIAN;
var dWorldTileSpriteColors =_seba.WEBGL.GLOBALS.buffers.worldTileSpriteColors.data;
var dWorldTileEntityProperties=_seba.WEBGL.GLOBALS.buffers.worldTileEntityProperties.data;
var dWorldTileTextureCoords =_seba.WEBGL.GLOBALS.buffers.worldTileTextureCoords.data;
var currentTexture=_seba.WEBGL.GLOBALS.textures[currentWorldTile.textureId];
var idx4=currentWorldTile.id*6*4; //2018-05-03 17:19:15 added alpha component
var dWorldTileEntityPropertiesIdx=currentWorldTile.id*6*_seba.WEBGL.WORLD.ENTITIES.GLOBALS.totalProperties;
var dWorldTileTextureCoordsIdx=currentWorldTile.id*6*2;
//vertex colors (3 points per vertex)
dWorldTileSpriteColors[idx4+0]=currentWorldTile.color1[0];
dWorldTileSpriteColors[idx4+1]=currentWorldTile.color1[1];
dWorldTileSpriteColors[idx4+2]=currentWorldTile.color1[2];
dWorldTileSpriteColors[idx4+3]=currentWorldTile.opacity;
dWorldTileSpriteColors[idx4+4]=currentWorldTile.color1[0];
dWorldTileSpriteColors[idx4+5]=currentWorldTile.color1[1];
dWorldTileSpriteColors[idx4+6]=currentWorldTile.color1[2];
dWorldTileSpriteColors[idx4+7]=currentWorldTile.opacity;
dWorldTileSpriteColors[idx4+8]=currentWorldTile.color1[0];
dWorldTileSpriteColors[idx4+9]=currentWorldTile.color1[1];
dWorldTileSpriteColors[idx4+10]=currentWorldTile.color1[2];
dWorldTileSpriteColors[idx4+11]=currentWorldTile.opacity;
dWorldTileSpriteColors[idx4+12]=currentWorldTile.color1[0];
dWorldTileSpriteColors[idx4+13]=currentWorldTile.color1[1];
dWorldTileSpriteColors[idx4+14]=currentWorldTile.color1[2];
dWorldTileSpriteColors[idx4+15]=currentWorldTile.opacity;
dWorldTileSpriteColors[idx4+16]=currentWorldTile.color1[0];
dWorldTileSpriteColors[idx4+17]=currentWorldTile.color1[1];
dWorldTileSpriteColors[idx4+18]=currentWorldTile.color1[2];
dWorldTileSpriteColors[idx4+19]=currentWorldTile.opacity;
dWorldTileSpriteColors[idx4+20]=currentWorldTile.color1[0];
dWorldTileSpriteColors[idx4+21]=currentWorldTile.color1[1];
dWorldTileSpriteColors[idx4+22]=currentWorldTile.color1[2];
dWorldTileSpriteColors[idx4+23]=currentWorldTile.opacity;
// simply copy the the selected texture coordinates
// into the 'slot' of the current world tile within the buffer of texture coordinates
dWorldTileTextureCoords[dWorldTileTextureCoordsIdx+ 0]=currentTexture.textureCoordinates[0];
dWorldTileTextureCoords[dWorldTileTextureCoordsIdx+ 1]=currentTexture.textureCoordinates[1];
dWorldTileTextureCoords[dWorldTileTextureCoordsIdx+ 2]=currentTexture.textureCoordinates[2];
dWorldTileTextureCoords[dWorldTileTextureCoordsIdx+ 3]=currentTexture.textureCoordinates[3];
dWorldTileTextureCoords[dWorldTileTextureCoordsIdx+ 4]=currentTexture.textureCoordinates[4];
dWorldTileTextureCoords[dWorldTileTextureCoordsIdx+ 5]=currentTexture.textureCoordinates[5];
dWorldTileTextureCoords[dWorldTileTextureCoordsIdx+ 6]=currentTexture.textureCoordinates[6];
dWorldTileTextureCoords[dWorldTileTextureCoordsIdx+ 7]=currentTexture.textureCoordinates[7];
dWorldTileTextureCoords[dWorldTileTextureCoordsIdx+ 8]=currentTexture.textureCoordinates[8];
dWorldTileTextureCoords[dWorldTileTextureCoordsIdx+ 9]=currentTexture.textureCoordinates[9];
dWorldTileTextureCoords[dWorldTileTextureCoordsIdx+10]=currentTexture.textureCoordinates[10];
dWorldTileTextureCoords[dWorldTileTextureCoordsIdx+11]=currentTexture.textureCoordinates[11];
dWorldTileEntityProperties[ dWorldTileEntityPropertiesIdx]=currentTexture.textureCoordinates[0]; //texture X coord
dWorldTileEntityProperties[++dWorldTileEntityPropertiesIdx]=currentTexture.layerId; //sprite layer id
dWorldTileEntityProperties[++dWorldTileEntityPropertiesIdx]=currentTexture.textureCoordinates[4]; //texture X1 coord
dWorldTileEntityProperties[++dWorldTileEntityPropertiesIdx]=0.0; //is light emitter,apply shadow attenuation,isFlippedX
//--
dWorldTileEntityProperties[++dWorldTileEntityPropertiesIdx]=currentTexture.textureCoordinates[0];
dWorldTileEntityProperties[++dWorldTileEntityPropertiesIdx]=currentTexture.layerId;
dWorldTileEntityProperties[++dWorldTileEntityPropertiesIdx]=currentTexture.textureCoordinates[4];
dWorldTileEntityProperties[++dWorldTileEntityPropertiesIdx]=0.0;
//--
dWorldTileEntityProperties[++dWorldTileEntityPropertiesIdx]=currentTexture.textureCoordinates[0];
dWorldTileEntityProperties[++dWorldTileEntityPropertiesIdx]=currentTexture.layerId;
dWorldTileEntityProperties[++dWorldTileEntityPropertiesIdx]=currentTexture.textureCoordinates[4];
dWorldTileEntityProperties[++dWorldTileEntityPropertiesIdx]=0.0;
//--
dWorldTileEntityProperties[++dWorldTileEntityPropertiesIdx]=currentTexture.textureCoordinates[0];
dWorldTileEntityProperties[++dWorldTileEntityPropertiesIdx]=currentTexture.layerId;
dWorldTileEntityProperties[++dWorldTileEntityPropertiesIdx]=currentTexture.textureCoordinates[4];
dWorldTileEntityProperties[++dWorldTileEntityPropertiesIdx]=0.0;
//--
dWorldTileEntityProperties[++dWorldTileEntityPropertiesIdx]=currentTexture.textureCoordinates[0];
dWorldTileEntityProperties[++dWorldTileEntityPropertiesIdx]=currentTexture.layerId;
dWorldTileEntityProperties[++dWorldTileEntityPropertiesIdx]=currentTexture.textureCoordinates[4];
dWorldTileEntityProperties[++dWorldTileEntityPropertiesIdx]=0.0;
//--
dWorldTileEntityProperties[++dWorldTileEntityPropertiesIdx]=currentTexture.textureCoordinates[0];
dWorldTileEntityProperties[++dWorldTileEntityPropertiesIdx]=currentTexture.layerId;
dWorldTileEntityProperties[++dWorldTileEntityPropertiesIdx]=currentTexture.textureCoordinates[4];
dWorldTileEntityProperties[++dWorldTileEntityPropertiesIdx]=0.0;
_seba.GLOBALS.isWorldTilesColorsDirty=1;
_seba.GLOBALS.isWorldTilesTextureCoordsDirty=1;
_seba.GLOBALS.isWorldTilesPropertiesDirty=1;
},
draw:function(now){ //proc DRAW! {green bold indent_3}
const _seba=SEBASTIAN; //performance lookup
//var lastTime=;
//console.log(now,lastTime);
var elapsed=now-_seba.GLOBALS.lastTime;
if (elapsed<_seba.GLOBALS.fpsInterval)
return;
//BEGIN RENDER
//console.log('frame',new Date());
var delta=elapsed;
if (delta>_seba.GLOBALS.fpsInterval) //do not allow overflow
delta=_seba.GLOBALS.fpsInterval;
_seba.GLOBALS.lastTime=now;
// return;
var oDate=new Date();
//color timekey
var h_key,m_key;
var hours,minutes;
if (_seba.GLOBALS.debugLightColors===1){ //allows setting the time manually
var tDate=new Date();
var unixtime=tDate.getTime();
unixtime+=_seba.GLOBALS.timeTravel*60*1000;
tDate.setTime(unixtime);
if (SEBASTIAN.GLOBALS.useUTCTime){
h_key=tDate.getUTCHours();
m_key=tDate.getUTCMinutes();
}else{
h_key=tDate.getHours();
m_key=tDate.getMinutes();
}
hours=h_key;
minutes=m_key;
}else{
if (SEBASTIAN.GLOBALS.useUTCTime){
h_key=oDate.getUTCHours();
m_key=oDate.getUTCMinutes();
}else{
h_key=oDate.getHours();
m_key=oDate.getMinutes();
}
hours=h_key;
minutes=m_key;
}
//if (h_key<10)
// h_key='0'+h_key;
//if (m_key<10)
// m_key='0'+m_key;
var colorKey=h_key+'_'+m_key;
var timeIdx=hours*60+minutes; //this allows us to index the day in minutes
//lookups
var shaderProgram =_seba.WEBGL.GLOBALS.shaderProgram;
var worldVertexPositionBuffer =_seba.WEBGL.WORLD.vertexPositionBuffer;
var worldVertexTextureCoordBuffer=_seba.WEBGL.WORLD.vertexTextureCoordBuffer;
var gl =_seba.GLOBALS.webgl_ctx; //lookup var
var pitch =_seba.WEBGL.WORLD.GLOBALS.pitch;
var yaw =_seba.WEBGL.WORLD.GLOBALS.yaw;
var pMatrix =_seba.WEBGL.WORLD.GLOBALS.pMatrix;
var mvMatrix =_seba.WEBGL.WORLD.GLOBALS.mvMatrix;
var xPos =_seba.WEBGL.WORLD.GLOBALS.xPos;
var yPos =_seba.WEBGL.WORLD.GLOBALS.yPos;
var zPos =_seba.WEBGL.WORLD.GLOBALS.zPos;
var degToRad =_seba.UTILS.degToRad;
var textures =_seba.WEBGL.textures;
var worldData =_seba.GLOBALS.worldData;
var entitiesTotalProperties =_seba.WEBGL.WORLD.ENTITIES.GLOBALS.totalProperties;
if (_seba.GLOBALS.lastTimeKey===null || _seba.GLOBALS.lastTimeKey!==colorKey){
//console.log(tDate);
//update time globals
_seba.GLOBALS.hours=h_key;//tDate.getHours();
_seba.GLOBALS.minutes=m_key;//tDate.getMinutes();
//refresh clock
var c_h_key=tDate.getHours();
var c_m_key=tDate.getMinutes();
if (c_h_key<10)
c_h_key='0'+c_h_key;
if (c_m_key<10)
c_m_key='0'+c_m_key;
SEBASTIAN.GLOBALS.clock.textContent=c_h_key+':'+c_m_key;
//map new colors
//console.log('map color',colorKey,SEBASTIAN.GLOBALS.lightColorTimeMap[colorKey].idx);
var brotherSun=worldData.entitiesNamePointer['sun'];
var sisterMoon=worldData.entitiesNamePointer['moon'];
var centerX=0;
var centerY=-25; //let's move the moon and the sun down a little bit so that they are more visible in our horizon
var circleRadius=120;
var distance=1440; //number of minutes in a day, corresponds to our time keys.
//We want our stars (star and satellite to be precise)
//to describe a circle based on the current minute.
//I want the sun to be high at midday and low at midnight.
//for the moon I want the exact opposite, ergo set a distance of 720 minutes between them
//720 minutes = half of the minutes in a day
//console.log(Math.acos(1-(Math.pow(distance/circleRadiusX,2)/2)));
//arccos( 1-(d/r)^2/2 )
//console.log(distance/circleRadiusX,2);
//https://stackoverflow.com/questions/17384663/canvas-move-object-in-circle
//https://www.safaribooksonline.com/library/view/html5-canvas/9781449308032/ch05s03.html
//console.log(Math.pow(distance/circleRadiusX,2)/2);
//console.log(Math.acos(1-Math.pow(distance/circleRadiusX,2)/2));
//console.log(colorKey);
var angle1=((SEBASTIAN.GLOBALS.lightColorTimeMap[colorKey].idx+720)*Math.PI/(360*2));
var angle2=((SEBASTIAN.GLOBALS.lightColorTimeMap[colorKey].idx)*Math.PI/(360*2));
//console.log();
brotherSun.x=centerX+Math.sin(angle1)*circleRadius;
brotherSun.y=centerY+Math.cos(angle1)*circleRadius;
brotherSun.angle=angle1; //used to simplify light position calculations
//brotherSun.z=-(centerY+Math.cos(angle)*circleRadius);
//I would say to put an opacity to the moon in order to make it disappear when it's sunny...
sisterMoon.x=centerX+Math.sin(angle2)*circleRadius;
sisterMoon.y=centerY+Math.cos(angle2)*circleRadius;
_seba.WEBGL.WORLD.ENTITIES.syncBuffersData(brotherSun);
_seba.WEBGL.WORLD.ENTITIES.syncBuffersData(sisterMoon);
//console.log((2 * Math.PI/60)*oDate.getSeconds());
//ctx.rotate(((2 * Math.PI) / 60) * oDate.getSeconds() + ((2 * Math.PI) / 60000) * oDate.getMilliseconds());
_seba.WEBGL.WORLD.GLOBALS.ambientLightColor=SEBASTIAN.GLOBALS.lightColorTimeMap[colorKey].a;
//_seba.WEBGL.WORLD.GLOBALS.skyLightColor=SEBASTIAN.GLOBALS.lightColorTimeMap[colorKey].a;
document.body.style.background=SEBASTIAN.GLOBALS.lightColorTimeMap[colorKey].g;
_seba.GLOBALS.lastTimeKey=colorKey;
//the position of the light has changed
_seba.WEBGL.WORLD.GLOBALS.isPointLightPositionDirty=1;
//the color of the light has changed
_seba.WEBGL.WORLD.GLOBALS.isAmbientLightDirty=1;
}
//read the mouse coordinates from the html
var mx=_seba.GLOBALS.mx;
var my=_seba.GLOBALS.my;
var oMx=_seba.GLOBALS.oMx;
var oMy=_seba.GLOBALS.oMy;
if (worldVertexTextureCoordBuffer===null || worldVertexPositionBuffer===null)
return;
if (_seba.WEBGL.WORLD.GLOBALS.isViewportDirty){ //browser window resized
// we need to calculate the perspective
// only if the viewport is resized
gl.viewport(0,0,gl.viewportWidth,gl.viewportHeight);
mat4.perspective(pMatrix,45,gl.viewportWidth/gl.viewportHeight,0.1,200.0);
gl.uniformMatrix4fv(shaderProgram.uPMatrix_var,false,pMatrix); //apply global projection matrix
_seba.WEBGL.WORLD.GLOBALS.isViewportDirty=0;
}
if (_seba.WEBGL.WORLD.GLOBALS.isCameraPositionDirty){ // modified camera position
gl.uniform3f(shaderProgram.uCameraTranslation_var,xPos,yPos,zPos); // pass the position of the camera to the vertex shader
_seba.WEBGL.WORLD.GLOBALS.isCameraPositionDirty=0;
// I have to perform entity position analysis and determine who is visible
// 0 = I do not care to reorder on z
// 1= I'm interested in determining visibility
// 0= I do not care to know who is under the mouse
_seba.WEBGL.WORLD.ENTITIES.checkEntitiesDepthVisibilityMousePos(0,1,0);
}
//clear the buffers
//ref: https://stackoverflow.com/questions/19469194/why-do-we-have-to-clear-depth-buffer-in-opengl-during-rendering/19469291#19469291
gl.clear(gl.COLOR_BUFFER_BIT | gl.GL_DEPTH_BUFFER_BIT);
// if a different rotation is applied than the one we have stored
// Let's do some nice calculations.
if (_seba.WEBGL.WORLD.GLOBALS.lPitch!==pitch || _seba.WEBGL.WORLD.GLOBALS.lYaw!==yaw){
mat4.identity(mvMatrix);
if (pitch!==0)
mat4.rotate(mvMatrix,mvMatrix,degToRad(-pitch), [1, 0, 0]);
if (yaw!==0)
mat4.rotate(mvMatrix,mvMatrix,degToRad(-yaw) , [0, 1, 0]);
_seba.WEBGL.WORLD.GLOBALS.lPitch=pitch;
_seba.WEBGL.WORLD.GLOBALS.lYaw=yaw;
//apply global viematrix only if a rotation is applied
gl.uniformMatrix4fv(shaderProgram.uMVMatrix_var,false,mvMatrix);
}
var foundTileUnderMouse=0;
var foundEntityUnderMouse=0;
var searchTile=0;
var searchEntity=0;
if (_seba.WEBGL.WORLD.GLOBALS.isPointLightPositionDirty){
// apply light-based calculations
// only if the position of the light has changed
var brotherSun=worldData.entitiesNamePointer['sun'];
var sisterMoon=worldData.entitiesNamePointer['moon'];
// change the vertical position of the light based on the time of day,
// this allows us, for example, to create the silhouette effect during sunset or sunrise
var sunLightVerticalDistance=_seba.WEBGL.WORLD.GLOBALS.sunLightVerticalDistance;
//sunset
sunLightVerticalDistance=SEBASTIAN.UTILS.applyTimeCalc({
parameter:sunLightVerticalDistance,
currentHour:hours,currentMinute:minutes,
fromHours :17,fromMinutes:45,
toHours :18,toMinutes :15,
fromValue:SEBASTIAN.WEBGL.WORLD.GLOBALS.sunLightVerticalDistance,
toValue :0,
});
//from after sunset to midnight
sunLightVerticalDistance=SEBASTIAN.UTILS.applyTimeCalc({
//logInfo:1,
applyTimeBouncing:0,
parameter:sunLightVerticalDistance,
currentHour:hours,currentMinute:minutes,
fromHours :18,fromMinutes:16,
toHours :23 ,toMinutes :59,
fromValue:SEBASTIAN.WEBGL.WORLD.GLOBALS.sunLightVerticalDistance,
toValue :-1600,
});
// from midnight to dawn
sunLightVerticalDistance=SEBASTIAN.UTILS.applyTimeCalc({
//logInfo:1,
applyTimeBouncing:0,
parameter:sunLightVerticalDistance,
currentHour:hours,currentMinute:minutes,
fromHours :0,fromMinutes:0,
toHours :5 ,toMinutes :44,
fromValue:-1600,
toValue :-400,
});
//Sunrise
sunLightVerticalDistance=SEBASTIAN.UTILS.applyTimeCalc({
applyTimeBouncing:0,
parameter:sunLightVerticalDistance,
currentHour:hours,currentMinute:minutes,
fromHours :5,fromMinutes:45,
toHours :6,toMinutes :15,
fromValue:-400,
toValue :SEBASTIAN.WEBGL.WORLD.GLOBALS.sunLightVerticalDistance,
});
//MOON
var moonLightVerticalDistance=-300;
moonLightVerticalDistance=SEBASTIAN.UTILS.applyTimeCalc({
//logInfo:1,
applyTimeBouncing:0,
parameter:moonLightVerticalDistance,
currentHour:hours,currentMinute:minutes,
fromHours :17,fromMinutes:16,
toHours :23 ,toMinutes :59,
fromValue:30,
toValue :150,
});
//from midnight to before dawn
moonLightVerticalDistance=SEBASTIAN.UTILS.applyTimeCalc({
//logInfo:1,
applyTimeBouncing:0,
parameter:moonLightVerticalDistance,
currentHour:hours,currentMinute:minutes,
fromHours :0,fromMinutes:0,
toHours :5 ,toMinutes :44,
fromValue:150,
toValue :50,
});
moonLightVerticalDistance=SEBASTIAN.UTILS.applyTimeCalc({
//logInfo:1,
applyTimeBouncing:0,
parameter:moonLightVerticalDistance,
currentHour:hours,currentMinute:minutes,
fromHours :5,fromMinutes:45,
toHours :6 ,toMinutes :0,
fromValue:50,
toValue :-300,
});
//the moon 'disappears' in the light of day
var moonOpacity=0;
moonOpacity=SEBASTIAN.UTILS.applyTimeCalc({
//logInfo:1,
applyTimeBouncing:0,
parameter:moonOpacity,
currentHour:hours,currentMinute:minutes,
fromHours :18,fromMinutes:0,
toHours :21 ,toMinutes :0,
fromValue:0,
toValue :1,
});
moonOpacity=SEBASTIAN.UTILS.applyTimeCalc({
//logInfo:1,
applyTimeBouncing:0,
parameter:moonOpacity,
currentHour:hours,currentMinute:minutes,
fromHours :21,fromMinutes:1,
toHours :23,toMinutes :59,
fromValue:1,
toValue :1,
});
moonOpacity=SEBASTIAN.UTILS.applyTimeCalc({
//logInfo:1,
applyTimeBouncing:0,
parameter:moonOpacity,
currentHour:hours,currentMinute:minutes,
fromHours :0,fromMinutes:0,
toHours :5,toMinutes :45,
fromValue:1,
toValue :0,
});
sisterMoon.opacity=moonOpacity;
_seba.WEBGL.WORLD.ENTITIES.syncBuffersData(sisterMoon); //update alpha
//console.log(moonLightVerticalDistance);
//console.log(parseFloat(t).toFixed(2),parseFloat(brotherSun.angle).toFixed(2),sunLightVerticalPosition);
gl.uniform3f(shaderProgram.uPointLighting1Location_var,brotherSun.x,brotherSun.y+sunLightVerticalDistance,brotherSun.z);
// instead of lowering the intensity of the moonlight in the vertex shader
// make sure that the light is less high than the satellite in order to illuminate less
gl.uniform3f(shaderProgram.uPointLighting2Location_var,sisterMoon.x,sisterMoon.y+moonLightVerticalDistance,sisterMoon.z);
_seba.WEBGL.WORLD.GLOBALS.isPointLightPositionDirty=0;
}
if (_seba.WEBGL.WORLD.GLOBALS.isAmbientLightDirty){
gl.uniform3fv(shaderProgram.uAmbientLightColorIntensity_var,_seba.WEBGL.WORLD.GLOBALS.ambientLightColorIntensity); //set ambient light intensity
gl.uniform3fv(shaderProgram.uAmbientLightColor_var,_seba.WEBGL.WORLD.GLOBALS.ambientLightColor); //set ambient light color
}
var drawCalls=0;
//proc TILES {indent_4}
//first we draw the static world, it has no transparencies
gl.depthMask(true); //this disables alpha blending, if we were to render a texture with alphait would have a solid background
var skippedTiles=0;
var vertexPositions=_seba.WEBGL.GLOBALS.buffers.worldTileVertexPositions.data;
for (var z=0,zEnd=worldData.world.length;z<zEnd;z++){
var currentWorldTile=worldData.world[z];
//if (z===20){
// console.log(vertexPositions[z*6*3+2]);
//}
if (_seba.WEBGL.WORLD.GLOBALS.isAmbientLightDirty){ // This must be done regardless of the visibility of the tile
var clockKey=_seba.GLOBALS.lastTimeKey;
var colorsPoolIdx=currentWorldTile.colorsPoolIdx;
var chosenColor=SEBASTIAN.GLOBALS.lightColorTimeMap[clockKey][colorsPoolIdx];
currentWorldTile.color1=chosenColor;
currentWorldTile.oColor1=chosenColor;
// it makes no sense to sync one tile at a time.
// run a single call at the end
//_seba.WEBGL.WORLD.syncTileBuffersData(currentWorldTile);
}
//drawCalls++;
}
//update the color of the tiles if necessary
if (_seba.WEBGL.WORLD.GLOBALS.isAmbientLightDirty){
_seba.WEBGL.WORLD.syncAllTileBuffersData();
}
// worldtile buffers data do not change with each drawcall
// only in the in case something changes during editing -> update them
gl.bindBuffer(gl.ARRAY_BUFFER,_seba.WEBGL.GLOBALS.buffers.worldTileTextureCoords.buffer);
if (_seba.GLOBALS.isWorldTilesTextureCoordsDirty){
gl.bufferData(gl.ARRAY_BUFFER,_seba.WEBGL.GLOBALS.buffers.worldTileTextureCoords.data,gl.DYNAMIC_DRAW);
_seba.GLOBALS.isWorldTilesTextureCoordsDirty=0;
}
gl.vertexAttribPointer(shaderProgram.aTextureCoord_var,2,gl.FLOAT,false,0,0);
gl.bindBuffer(gl.ARRAY_BUFFER,_seba.WEBGL.GLOBALS.buffers.worldTileTranslations.buffer);
gl.vertexAttribPointer(shaderProgram.aEntityTranslation_var,3,gl.FLOAT,false,0,0);
//replace the color buffer data once a minute (see WORLD.syncTileBuffersData)
gl.bindBuffer(gl.ARRAY_BUFFER,_seba.WEBGL.GLOBALS.buffers.worldTileSpriteColors.buffer);
if (_seba.GLOBALS.isWorldTilesColorsDirty){
gl.bufferSubData(gl.ARRAY_BUFFER,0,_seba.WEBGL.GLOBALS.buffers.worldTileSpriteColors.data);
_seba.GLOBALS.isWorldTilesColorsDirty=0;
}
gl.vertexAttribPointer(shaderProgram.aEntityColor_var,4,gl.FLOAT,false,0,0);
gl.bindBuffer(gl.ARRAY_BUFFER,_seba.WEBGL.GLOBALS.buffers.worldTileEntityProperties.buffer);
if (_seba.GLOBALS.isWorldTilesPropertiesDirty){
gl.bufferSubData(gl.ARRAY_BUFFER,0,_seba.WEBGL.GLOBALS.buffers.worldTileEntityProperties.data);
_seba.GLOBALS.isWorldTilesPropertiesDirty=0;
}
gl.vertexAttribPointer(shaderProgram.aEntityProperties_var,entitiesTotalProperties,gl.FLOAT,false,0,0);
gl.bindBuffer (gl.ARRAY_BUFFER,_seba.WEBGL.GLOBALS.buffers.worldTileVertexPositions.buffer);
if (_seba.GLOBALS.isWorldTilesVerticesPositionDirty){
//since we allow editing of the vertices, apply them for the current drawcall if they have been modified
gl.bufferSubData(gl.ARRAY_BUFFER,0,_seba.WEBGL.GLOBALS.buffers.worldTileVertexPositions.data); // this makes the position of the vertices dynamic, in case we use static terrain we can remove this line
_seba.GLOBALS.isWorldTilesVerticesPositionDirty=0;
}
gl.vertexAttribPointer(shaderProgram.aVertexPosition_var,3,gl.FLOAT,false,0,0);
gl.drawArrays(gl.TRIANGLES,0,_seba.WEBGL.GLOBALS.buffers.worldTileVertexPositions.count);
//----------------------
//proc ENTITIES {indent_4}
//now we draw entities that have transparent PNGs as textures
var depths=_seba.WEBGL.WORLD.ENTITIES.GLOBALS.depthSorted;
//writing into the depth buffer is now disabled.
gl.depthMask(false); //disabling depth mask we can have alpha objects but we have to sort them
for (var z=0,zEnd=worldData.entities.length;z<zEnd;z++){
var currentEntity=worldData.entities[depths[z].entityId]; // obtain the ordered entities based on depth, and we use the painter algorithm to draw them
if (currentEntity.isHidden===1) // entities such as clusters are hidden. (in fact they are always drawn because the data is in the buffer array, but with negative x)
continue;
//todo: this is perhaps less expensive to do once and for all entities
if (_seba.WEBGL.WORLD.GLOBALS.isAmbientLightDirty){
// update color pool if necessary
// this same routine manages the dynamic color of the single entities dDMKCWhHp4
if (currentEntity.hasPoolColor===1){
var clockKey=_seba.GLOBALS.lastTimeKey;
var colorsPoolIdx=currentEntity.colorsPoolIdx;
var chosenColor=SEBASTIAN.GLOBALS.lightColorTimeMap[clockKey][colorsPoolIdx];
currentEntity.color1=chosenColor;
currentEntity.oColor1=chosenColor;
SEBASTIAN.WEBGL.WORLD.ENTITIES.syncBuffersData(currentEntity);
}
}
_seba.WEBGL.WORLD.ENTITIES.animate(currentEntity.id,delta,timeIdx);
if (currentEntity.isVisible===0) // non-visible entities are still animated at position level, but not geometry
continue;
_seba.WEBGL.WORLD.ENTITIES.animateGeometry(currentEntity.id,delta);
}
//proc reset isAmbientLightDirty flag {indent_4}
if (_seba.WEBGL.WORLD.GLOBALS.isAmbientLightDirty){
_seba.WEBGL.WORLD.GLOBALS.isAmbientLightDirty=0;
}
gl.bindBuffer(gl.ARRAY_BUFFER,_seba.WEBGL.GLOBALS.buffers.entitiesTextureCoordsZ.buffer);
gl.bufferSubData(gl.ARRAY_BUFFER,0,_seba.WEBGL.GLOBALS.buffers.entitiesTextureCoordsZ.data);
gl.vertexAttribPointer(shaderProgram.aTextureCoord_var,2,gl.FLOAT,false,0,0);
gl.bindBuffer(gl.ARRAY_BUFFER,_seba.WEBGL.GLOBALS.buffers.entitiesTranslationsZ.buffer);
gl.bufferSubData(gl.ARRAY_BUFFER,0,_seba.WEBGL.GLOBALS.buffers.entitiesTranslationsZ.data);
gl.vertexAttribPointer(shaderProgram.aEntityTranslation_var,3,gl.FLOAT,false,0,0);
gl.bindBuffer(gl.ARRAY_BUFFER,_seba.WEBGL.GLOBALS.buffers.entitiesSpriteColorsZ.buffer);
gl.bufferSubData(gl.ARRAY_BUFFER,0,_seba.WEBGL.GLOBALS.buffers.entitiesSpriteColorsZ.data);
gl.vertexAttribPointer(shaderProgram.aEntityColor_var,4,gl.FLOAT,false,0,0);
gl.bindBuffer(gl.ARRAY_BUFFER,_seba.WEBGL.GLOBALS.buffers.entitiesPropertiesZ.buffer);
gl.bufferSubData(gl.ARRAY_BUFFER,0,_seba.WEBGL.GLOBALS.buffers.entitiesPropertiesZ.data);
gl.vertexAttribPointer(shaderProgram.aEntityProperties_var,entitiesTotalProperties,gl.FLOAT,false,0,0);
gl.bindBuffer (gl.ARRAY_BUFFER,_seba.WEBGL.GLOBALS.buffers.entitiesVertexPositionsZ.buffer);
gl.bufferSubData(gl.ARRAY_BUFFER,0,_seba.WEBGL.GLOBALS.buffers.entitiesVertexPositionsZ.data);
gl.vertexAttribPointer(shaderProgram.aVertexPosition_var,3,gl.FLOAT,false,0,0);
gl.drawArrays(gl.TRIANGLES,0,_seba.WEBGL.GLOBALS.buffers.entitiesVertexPositionsZ.count);
//It was fun. ALL DONE.
},
onloadHandler:function(data,callback){ //proc onloadHandler WORLD/SCENE {green indent_3}
var gl=SEBASTIAN.GLOBALS.webgl_ctx; //lookup var
var worldData=JSON.parse(data);
var _seba=SEBASTIAN;
_seba.GLOBALS.worldData=worldData;
//console.log(worldData.entities.length);
//proc WORLD ENTITIES {violet bold indent_4}
for (var z=0,zEnd=worldData.entities.length;z<zEnd;z++){
worldData.entities[z].id=z;
worldData.entities[z].x=parseFloat(worldData.entities[z].x);
worldData.entities[z].y=parseFloat(worldData.entities[z].y);
worldData.entities[z].z=parseFloat(worldData.entities[z].z);
//handle undef neeeded props
if (typeof worldData.entities[z].isLivingBeing==='undefined')
worldData.entities[z].isLivingBeing=0;
if (typeof worldData.entities[z].color1==='undefined')
worldData.entities[z].color1=[1.0,1.0,1.0];
worldData.entities[z].oColor1=worldData.entities[z].color1; //original color1
if (typeof worldData.entities[z].speed==='undefined'){
worldData.entities[z].speed=0;
}
worldData.entities[z].oTextureId=worldData.entities[z].textureId; // save the original texture without animations, we need it to save the scene
// init of the entities read from file
SEBASTIAN.WEBGL.WORLD.ENTITIES.define(z);
//SEBASTIAN.WEBGL.WORLD.dynamicVertexTextureCoordBuffers[z]=worldVertexTextureCoordBuffer;
}
// after the define cycle we have the actual number of existing entities
//console.log(worldData.entities.length);
//init buffers
_seba.WEBGL.GLOBALS.buffers.entitiesVertexPositions={};
// create buffers for Z sorting
// the vertex coordinate buffer exists in two forms:
// not ordered and ordered in z
// for the representation of the entities we use the z-sorted buffer
_seba.WEBGL.GLOBALS.buffers.entitiesTextureCoordsZ={
buffer:gl.createBuffer(),
data:new Float32Array(worldData.entities.length * 6 * 2)
};
//--
_seba.WEBGL.GLOBALS.buffers.entitiesVertexPositionsZ={ // identical to entitiesVertexPositions but sorted into z, we keep the unordered buffer to access the original coordinates of the entities
buffer:gl.createBuffer(),
data:new Float32Array(worldData.entities.length * 6 * 3),
count:6*worldData.entities.length
};
//--
_seba.WEBGL.GLOBALS.buffers.entitiesTranslationsZ={
buffer:gl.createBuffer(),
data:new Float32Array(worldData.entities.length * 6 * 3)
};
//--
_seba.WEBGL.GLOBALS.buffers.entitiesSpriteColorsZ={
buffer:gl.createBuffer(),
data:new Float32Array(worldData.entities.length * 6 * 4)
};
//--
_seba.WEBGL.GLOBALS.buffers.entitiesPropertiesZ={
buffer:gl.createBuffer(),
data:new Float32Array(worldData.entities.length * 6 * _seba.WEBGL.WORLD.ENTITIES.GLOBALS.totalProperties) //3 proprietà per ogni entity
}
//
var bEntitiesVertexPositions=_seba.WEBGL.GLOBALS.buffers.entitiesVertexPositions;
bEntitiesVertexPositions.data=new Float32Array(worldData.entities.length * 6 * 3);
//fill entities buffer data
var bEntitiesVertexPositionsIdx=0;
for (var z=0,zEnd=worldData.entities.length;z<zEnd;z++){
var currentEntity=worldData.entities[z];
var currentTexture=_seba.WEBGL.GLOBALS.textures[currentEntity.oTextureId];
if (typeof currentTexture==='undefined'){
currentTexture=_seba.WEBGL.GLOBALS.textures['pavement_01'];
console.log(currentEntity.oTextureId,'->','pavement_01');
}
if (currentEntity.isStanding===1){
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+0]=0.0*currentEntity.scale*currentTexture.scaleX;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+1]=1.0*currentEntity.scale*currentTexture.scaleY;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+2]=0.0;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+3]=0.0*currentEntity.scale*currentTexture.scaleX;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+4]=0.0*currentEntity.scale*currentTexture.scaleY;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+5]=0.0;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+6]=1.0*currentEntity.scale*currentTexture.scaleX;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+7]=0.0*currentEntity.scale*currentTexture.scaleY;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+8]=0.0;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+9] =0.0*currentEntity.scale*currentTexture.scaleX;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+10]=1.0*currentEntity.scale*currentTexture.scaleY;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+11]=0.0;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+12]=1.0*currentEntity.scale*currentTexture.scaleX;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+13]=1.0*currentEntity.scale*currentTexture.scaleY;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+14]=0.0;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+15]=1.0*currentEntity.scale*currentTexture.scaleX;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+16]=0.0*currentEntity.scale*currentTexture.scaleY;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+17]=0.0;
//if (currentEntity.oTextureId.indexOf('grass')!==-1){
// console.log(currentEntity.oTextureId,currentEntity.scale,currentTexture.scaleX);
//}
}else{ //entities such as water
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+0]=0.0;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+1]=0.0;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+2]=0.0;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+3]=0.0;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+4]=0.0;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+5]=1.0*currentEntity.scale*currentTexture.scaleY;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+6]=1.0*currentEntity.scale*currentTexture.scaleX;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+7]=0.0;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+8]=1.0*currentEntity.scale*currentTexture.scaleY;;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+9] =0.0;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+10]=0.0;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+11]=0.0;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+12]=1.0*currentEntity.scale*currentTexture.scaleX;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+13]=0.0;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+14]=0.0;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+15]=1.0*currentEntity.scale*currentTexture.scaleX;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+16]=0.0;
bEntitiesVertexPositions.data[bEntitiesVertexPositionsIdx+17]=1.0*currentEntity.scale*currentTexture.scaleY;
}
bEntitiesVertexPositionsIdx+=18;
}
//Once the buffers are created, sort them by the z by position
//of the entities
SEBASTIAN.WEBGL.WORLD.ENTITIES.sortZBuffersByEntityPosition();
//proc WORLD TILES {violet bold indent_4}
//proc PARSE WORLD FILE > STATIC VERTEX DATA {yellow indent_4}
//---------
//STATIC WORLD DATA
//vertices that can not move
//--
var wordlTileColumns=SEBASTIAN.WEBGL.WORLD.GLOBALS.columns;
var wordlTileTotalTiles=wordlTileColumns*SEBASTIAN.WEBGL.WORLD.GLOBALS.rows;
var offsetX=0;
var offsetZ=0;
var tileScale=1;
var currentTexture; //pointer to the texture applied to the tile
//2018-03-22 13:13:51 add dynamic colors to world tiles
var tileDefaultPoolColor='C1'; //proc default tile color {violet indent_5}
//--
var h_key=SEBASTIAN.GLOBALS.hours;//=tDate.getUTCHours();
var m_key=SEBASTIAN.GLOBALS.minutes;//=tDate.getUTCMinutes();
var colorKey=h_key+'_'+m_key;
var colorsPoolIdx='p'+tileDefaultPoolColor;
var chosenTileColor=SEBASTIAN.GLOBALS.lightColorTimeMap[colorKey][colorsPoolIdx];
var counter=0;
var initOffsetX=offsetX;
if (typeof worldData.world==='undefined')
worldData.world=[];
//init buffers
_seba.WEBGL.GLOBALS.buffers.worldTileTextureCoords={};
_seba.WEBGL.GLOBALS.buffers.worldTileVertexPositions={};
_seba.WEBGL.GLOBALS.buffers.worldTileTranslations={};
_seba.WEBGL.GLOBALS.buffers.worldTileSpriteColors={};
_seba.WEBGL.GLOBALS.buffers.worldTileEntityProperties={};
var bWorldTileTextureCoords=_seba.WEBGL.GLOBALS.buffers.worldTileTextureCoords;
var bWorldTileVertexPositions=_seba.WEBGL.GLOBALS.buffers.worldTileVertexPositions;
var bWorldTileTranslations=_seba.WEBGL.GLOBALS.buffers.worldTileTranslations;
var bWorldTileSpriteColors=_seba.WEBGL.GLOBALS.buffers.worldTileSpriteColors;
var bWorldTileEntityProperties=_seba.WEBGL.GLOBALS.buffers.worldTileEntityProperties;
//--
var bWorldTileTextureCoordsIdx=0;
var bWorldTileVertexPositionsIdx=0;
var bWorldTileTranslationsIdx=0;
var bWorldTileSpriteColorsIdx=0;
var bWorldTileEntityPropertiesIdx=0;
// for textures we need two coordinates for each vertex of the two triangles
// the two triangles make 6 vertices in total
bWorldTileTextureCoords.data=new Float32Array(wordlTileTotalTiles * 6 * 2);
//for the buffer of the vertices we need 3 coordinates for each vertex of the two triangles
//then 3 coordinates (x, y, z) for each of the 6 vertices = 6 * 3
bWorldTileVertexPositions.data=new Float32Array(wordlTileTotalTiles * 6 * 3);
bWorldTileTranslations.data=new Float32Array(wordlTileTotalTiles * 6 * 3);
bWorldTileSpriteColors.data=new Float32Array(wordlTileTotalTiles * 6 * 4); //2018-05-03 16:48:33 added alpha r,g,b,a
bWorldTileEntityProperties.data=new Float32Array(wordlTileTotalTiles * 6 * _seba.WEBGL.WORLD.ENTITIES.GLOBALS.totalProperties);
if (SEBASTIAN.GLOBALS.loadSavedScene){
//load the scene.json file
for (var z=0,zEnd=worldData.world.length;z<zEnd;z++){
var currentWorldTile=worldData.world[z];
//handle undef neeeded props
if (typeof currentWorldTile.color1==='undefined')
currentWorldTile.color1=[1.0,1.0,1.0];
currentWorldTile.oColor1=currentWorldTile.color1; //original color
currentWorldTile.oTextureId=currentWorldTile.textureId; //original texture so we are able able to change it during selection and saving
}
//set camera from scene
if (typeof worldData.camera!=='undefined'){
SEBASTIAN.WEBGL.WORLD.GLOBALS.yPos=worldData.camera.yPos;
SEBASTIAN.WEBGL.WORLD.GLOBALS.xPos=worldData.camera.xPos;
SEBASTIAN.WEBGL.WORLD.GLOBALS.zPos=worldData.camera.zPos;
SEBASTIAN.WEBGL.WORLD.GLOBALS.pitch=worldData.camera.pitch;
SEBASTIAN.WEBGL.WORLD.GLOBALS.yaw=worldData.camera.yaw;
}
//restore vertices position into the typed Array
bWorldTileVertexPositions.data.set(worldData.worldTilesVertices);
}
for (var z=0;z<wordlTileTotalTiles;z++){
//set default tile data
if (typeof worldData.world[z]==='undefined')
worldData.world[z]={};
var currentWorldTile=worldData.world[z];
currentWorldTile.id=z;
if (!SEBASTIAN.GLOBALS.loadSavedScene){
currentWorldTile.color1=[1.0,1.0,1.0];
currentWorldTile.opacity=1.0;
currentWorldTile.oColor1=worldData.world[z].color1;
currentWorldTile.textureId='pavement_01';
currentWorldTile.oTextureId=worldData.world[z].textureId; //saved so we can 'select' a tile by switching textures
currentWorldTile.colorsPoolIdx=colorsPoolIdx; //set colorPool index
currentTexture=_seba.WEBGL.GLOBALS.textures[currentWorldTile.textureId];
//vertices texture coordinates
// 0.0 0.0 0.0 0.0 1.0 //a 0, 1, 2
// 0.0 0.0 1.0 0.0 0.0 //b 3, 4, 5
// 1.0 0.0 1.0 1.0 0.0 //c 6, 7, 8
//
// 0.0 0.0 0.0 0.0 1.0 //d 9,10,11
// 1.0 0.0 0.0 1.0 1.0 //e 12,13,14
// 1.0 0.0 1.0 1.0 0.0 //f 15,16,17
//vertexPositions
bWorldTileVertexPositions.data[bWorldTileVertexPositionsIdx+0]=0.0*tileScale*currentTexture.scaleX+offsetX;
bWorldTileVertexPositions.data[bWorldTileVertexPositionsIdx+1]=0.0;
bWorldTileVertexPositions.data[bWorldTileVertexPositionsIdx+2]=0.0*tileScale*currentTexture.scaleY+offsetZ;
bWorldTileVertexPositions.data[bWorldTileVertexPositionsIdx+3]=0.0*tileScale*currentTexture.scaleX+offsetX;
bWorldTileVertexPositions.data[bWorldTileVertexPositionsIdx+4]=0.0;
bWorldTileVertexPositions.data[bWorldTileVertexPositionsIdx+5]=1.0*tileScale*currentTexture.scaleY+offsetZ;
bWorldTileVertexPositions.data[bWorldTileVertexPositionsIdx+6]=1.0*tileScale*currentTexture.scaleX+offsetX;
bWorldTileVertexPositions.data[bWorldTileVertexPositionsIdx+7]=0.0;
bWorldTileVertexPositions.data[bWorldTileVertexPositionsIdx+8]=1.0*tileScale*currentTexture.scaleY+offsetZ;
bWorldTileVertexPositions.data[bWorldTileVertexPositionsIdx+9]=0.0*tileScale*currentTexture.scaleX+offsetX;
bWorldTileVertexPositions.data[bWorldTileVertexPositionsIdx+10]=0.0;
bWorldTileVertexPositions.data[bWorldTileVertexPositionsIdx+11]=0.0*tileScale*currentTexture.scaleY+offsetZ;
bWorldTileVertexPositions.data[bWorldTileVertexPositionsIdx+12]=1.0*tileScale*currentTexture.scaleX+offsetX;
bWorldTileVertexPositions.data[bWorldTileVertexPositionsIdx+13]=0.0;
bWorldTileVertexPositions.data[bWorldTileVertexPositionsIdx+14]=0.0*tileScale*currentTexture.scaleY+offsetZ;
bWorldTileVertexPositions.data[bWorldTileVertexPositionsIdx+15]=1.0*tileScale*currentTexture.scaleX+offsetX;
bWorldTileVertexPositions.data[bWorldTileVertexPositionsIdx+16]=0.0;
bWorldTileVertexPositions.data[bWorldTileVertexPositionsIdx+17]=1.0*tileScale*currentTexture.scaleY+offsetZ;
bWorldTileVertexPositionsIdx+=18;
}else{
//if we do not load a scene, we just need to set the current texture
currentTexture=_seba.WEBGL.GLOBALS.textures[currentWorldTile.textureId];
}
//copy the coordinates of the selected texture into
//the current world tile slot in the texture coordinate buffer
bWorldTileTextureCoords.data[bWorldTileTextureCoordsIdx+ 0]=currentTexture.textureCoordinates[0];
bWorldTileTextureCoords.data[bWorldTileTextureCoordsIdx+ 1]=currentTexture.textureCoordinates[1];
bWorldTileTextureCoords.data[bWorldTileTextureCoordsIdx+ 2]=currentTexture.textureCoordinates[2];
bWorldTileTextureCoords.data[bWorldTileTextureCoordsIdx+ 3]=currentTexture.textureCoordinates[3];
bWorldTileTextureCoords.data[bWorldTileTextureCoordsIdx+ 4]=currentTexture.textureCoordinates[4];
bWorldTileTextureCoords.data[bWorldTileTextureCoordsIdx+ 5]=currentTexture.textureCoordinates[5];
bWorldTileTextureCoords.data[bWorldTileTextureCoordsIdx+ 6]=currentTexture.textureCoordinates[6];
bWorldTileTextureCoords.data[bWorldTileTextureCoordsIdx+ 7]=currentTexture.textureCoordinates[7];
bWorldTileTextureCoords.data[bWorldTileTextureCoordsIdx+ 8]=currentTexture.textureCoordinates[8];
bWorldTileTextureCoords.data[bWorldTileTextureCoordsIdx+ 9]=currentTexture.textureCoordinates[9];
bWorldTileTextureCoords.data[bWorldTileTextureCoordsIdx+10]=currentTexture.textureCoordinates[10];
bWorldTileTextureCoords.data[bWorldTileTextureCoordsIdx+11]=currentTexture.textureCoordinates[11];
bWorldTileTextureCoordsIdx+=12;
bWorldTileTranslations.data[bWorldTileTranslationsIdx+ 0]=0.0;
bWorldTileTranslations.data[bWorldTileTranslationsIdx+ 1]=0.0;
bWorldTileTranslations.data[bWorldTileTranslationsIdx+ 2]=0.0;
bWorldTileTranslations.data[bWorldTileTranslationsIdx+ 3]=0.0;
bWorldTileTranslations.data[bWorldTileTranslationsIdx+ 4]=0.0;
bWorldTileTranslations.data[bWorldTileTranslationsIdx+ 5]=0.0;
bWorldTileTranslations.data[bWorldTileTranslationsIdx+ 6]=0.0;
bWorldTileTranslations.data[bWorldTileTranslationsIdx+ 7]=0.0;
bWorldTileTranslations.data[bWorldTileTranslationsIdx+ 8]=0.0;
bWorldTileTranslations.data[bWorldTileTranslationsIdx+ 9]=0.0;
bWorldTileTranslations.data[bWorldTileTranslationsIdx+ 10]=0.0;
bWorldTileTranslations.data[bWorldTileTranslationsIdx+ 11]=0.0;
bWorldTileTranslations.data[bWorldTileTranslationsIdx+ 12]=0.0;
bWorldTileTranslations.data[bWorldTileTranslationsIdx+ 13]=0.0;
bWorldTileTranslations.data[bWorldTileTranslationsIdx+ 14]=0.0;
bWorldTileTranslations.data[bWorldTileTranslationsIdx+ 15]=0.0;
bWorldTileTranslations.data[bWorldTileTranslationsIdx+ 16]=0.0;
bWorldTileTranslations.data[bWorldTileTranslationsIdx+ 17]=0.0;
bWorldTileTranslationsIdx+=18;
//colors
//we do not need to specify an initial color because
//the first draw will automatically determine the color of the tiles based
//on their colorDynamic property
bWorldTileSpriteColors.data[bWorldTileSpriteColorsIdx+0 ]=1.0;//r
bWorldTileSpriteColors.data[bWorldTileSpriteColorsIdx+1 ]=1.0;//g
bWorldTileSpriteColors.data[bWorldTileSpriteColorsIdx+2 ]=1.0;//b
bWorldTileSpriteColors.data[bWorldTileSpriteColorsIdx+3 ]=currentWorldTile.opacity;//a
bWorldTileSpriteColors.data[bWorldTileSpriteColorsIdx+4 ]=1.0;
bWorldTileSpriteColors.data[bWorldTileSpriteColorsIdx+5 ]=1.0;
bWorldTileSpriteColors.data[bWorldTileSpriteColorsIdx+6 ]=1.0;
bWorldTileSpriteColors.data[bWorldTileSpriteColorsIdx+7 ]=currentWorldTile.opacity;
bWorldTileSpriteColors.data[bWorldTileSpriteColorsIdx+8 ]=1.0;
bWorldTileSpriteColors.data[bWorldTileSpriteColorsIdx+9 ]=1.0;
bWorldTileSpriteColors.data[bWorldTileSpriteColorsIdx+10 ]=1.0;
bWorldTileSpriteColors.data[bWorldTileSpriteColorsIdx+11 ]=currentWorldTile.opacity;
bWorldTileSpriteColors.data[bWorldTileSpriteColorsIdx+12]=1.0;
bWorldTileSpriteColors.data[bWorldTileSpriteColorsIdx+13]=1.0;
bWorldTileSpriteColors.data[bWorldTileSpriteColorsIdx+14]=1.0;
bWorldTileSpriteColors.data[bWorldTileSpriteColorsIdx+15]=currentWorldTile.opacity;
bWorldTileSpriteColors.data[bWorldTileSpriteColorsIdx+16]=1.0;
bWorldTileSpriteColors.data[bWorldTileSpriteColorsIdx+17]=1.0;
bWorldTileSpriteColors.data[bWorldTileSpriteColorsIdx+18]=1.0;
bWorldTileSpriteColors.data[bWorldTileSpriteColorsIdx+19]=currentWorldTile.opacity;
bWorldTileSpriteColors.data[bWorldTileSpriteColorsIdx+20]=1.0;
bWorldTileSpriteColors.data[bWorldTileSpriteColorsIdx+21]=1.0;
bWorldTileSpriteColors.data[bWorldTileSpriteColorsIdx+22]=1.0;
bWorldTileSpriteColors.data[bWorldTileSpriteColorsIdx+23]=currentWorldTile.opacity;
bWorldTileSpriteColorsIdx+=24;
//proc TILES.PROPERTIES.FLAGS {violet bold indent_4}
bWorldTileEntityProperties.data[ bWorldTileEntityPropertiesIdx]=currentTexture.oX; //texture coord x
bWorldTileEntityProperties.data[++bWorldTileEntityPropertiesIdx]=currentTexture.layerId; //sprite layer id
bWorldTileEntityProperties.data[++bWorldTileEntityPropertiesIdx]=currentTexture.textureCoordinates[4]; //texture coord x1
bWorldTileEntityProperties.data[++bWorldTileEntityPropertiesIdx]=0.0; //is light emitter, apply shadow attenuation, is x flipped
//--
bWorldTileEntityProperties.data[++bWorldTileEntityPropertiesIdx]=currentTexture.oX;
bWorldTileEntityProperties.data[++bWorldTileEntityPropertiesIdx]=currentTexture.layerId;
bWorldTileEntityProperties.data[++bWorldTileEntityPropertiesIdx]=currentTexture.textureCoordinates[4];
bWorldTileEntityProperties.data[++bWorldTileEntityPropertiesIdx]=0.0;
//--
bWorldTileEntityProperties.data[++bWorldTileEntityPropertiesIdx]=currentTexture.oX;
bWorldTileEntityProperties.data[++bWorldTileEntityPropertiesIdx]=currentTexture.layerId;
bWorldTileEntityProperties.data[++bWorldTileEntityPropertiesIdx]=currentTexture.textureCoordinates[4];
bWorldTileEntityProperties.data[++bWorldTileEntityPropertiesIdx]=0.0;
//--
bWorldTileEntityProperties.data[++bWorldTileEntityPropertiesIdx]=currentTexture.oX;
bWorldTileEntityProperties.data[++bWorldTileEntityPropertiesIdx]=currentTexture.layerId;
bWorldTileEntityProperties.data[++bWorldTileEntityPropertiesIdx]=currentTexture.textureCoordinates[4];
bWorldTileEntityProperties.data[++bWorldTileEntityPropertiesIdx]=0.0;
//--
bWorldTileEntityProperties.data[++bWorldTileEntityPropertiesIdx]=currentTexture.oX;
bWorldTileEntityProperties.data[++bWorldTileEntityPropertiesIdx]=currentTexture.layerId;
bWorldTileEntityProperties.data[++bWorldTileEntityPropertiesIdx]=currentTexture.textureCoordinates[4];
bWorldTileEntityProperties.data[++bWorldTileEntityPropertiesIdx]=0.0;
//--
bWorldTileEntityProperties.data[++bWorldTileEntityPropertiesIdx]=currentTexture.oX;
bWorldTileEntityProperties.data[++bWorldTileEntityPropertiesIdx]=currentTexture.layerId;
bWorldTileEntityProperties.data[++bWorldTileEntityPropertiesIdx]=currentTexture.textureCoordinates[4];
bWorldTileEntityProperties.data[++bWorldTileEntityPropertiesIdx]=0.0;
bWorldTileEntityPropertiesIdx++;
counter++;
offsetX+=tileScale*1;
if (counter%wordlTileColumns===0){
offsetX=initOffsetX;
offsetZ+=tileScale;
}
}
//create the buffers for the worldtiles
_seba.WEBGL.GLOBALS.buffers.worldTileTextureCoords.buffer=gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,_seba.WEBGL.GLOBALS.buffers.worldTileTextureCoords.buffer);
gl.bufferData(gl.ARRAY_BUFFER,_seba.WEBGL.GLOBALS.buffers.worldTileTextureCoords.data,gl.DYNAMIC_DRAW);
_seba.WEBGL.GLOBALS.buffers.worldTileVertexPositions.buffer=gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,_seba.WEBGL.GLOBALS.buffers.worldTileVertexPositions.buffer);
gl.bufferData(gl.ARRAY_BUFFER,_seba.WEBGL.GLOBALS.buffers.worldTileVertexPositions.data,gl.DYNAMIC_DRAW);
_seba.WEBGL.GLOBALS.buffers.worldTileVertexPositions.count=wordlTileTotalTiles*6;
//console.log(_seba.WEBGL.GLOBALS.buffers.worldTileVertexPositions.data,wordlTileTotalTiles);
_seba.WEBGL.GLOBALS.buffers.worldTileSpriteColors.buffer=gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,_seba.WEBGL.GLOBALS.buffers.worldTileSpriteColors.buffer);
gl.bufferData(gl.ARRAY_BUFFER,_seba.WEBGL.GLOBALS.buffers.worldTileSpriteColors.data,gl.DYNAMIC_DRAW);
_seba.WEBGL.GLOBALS.buffers.worldTileEntityProperties.buffer=gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,_seba.WEBGL.GLOBALS.buffers.worldTileEntityProperties.buffer);
gl.bufferData(gl.ARRAY_BUFFER,_seba.WEBGL.GLOBALS.buffers.worldTileEntityProperties.data,gl.DYNAMIC_DRAW);
//the position of the world tiles never change
//so set the buffer data just once
_seba.WEBGL.GLOBALS.buffers.worldTileTranslations.buffer=gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER,_seba.WEBGL.GLOBALS.buffers.worldTileTranslations.buffer);
gl.bufferData(gl.ARRAY_BUFFER,_seba.WEBGL.GLOBALS.buffers.worldTileTranslations.data,gl.STATIC_DRAW); //2018-02-22 08:58:06 opz. avevo messo worldTileVertexPositions al posto di worldTileTranslations e tutti i tile venivano ovviamente cannati....
callback();
},
ENTITIES:{ //proc ENTITIES {orange indent_3}
GLOBALS:{ //proc WEBGL.WORLD.ENTITIES.GLOBALS {orange indent_4}
depthSorted:[], //array with list of entity ids sorted by camera to be drawn with the painter's algorithm
//NOTE: it is not possible to have a vertextattibute with dim greather than 4 {indent_4}
// ref: http://docs.gl/gl3/glVertexAttribPointer -> errors
totalProperties:4,
},
init:function(){ //proc init {green indent_4}
var gl=SEBASTIAN.GLOBALS.webgl_ctx; //lookup var
//define a polygon -> vertical 1x1 square at offset 0,0
var vertexPositions=[
0.0, 1.0, 0.0 ,
0.0, 0.0, 0.0 ,
1.0, 0.0, 0.0 ,
0.0, 1.0, 0.0 ,
1.0, 1.0, 0.0 ,
1.0, 0.0, 0.0
];
var vertexTextureCoords=[
0.0, 1.0,
0.0, 0.0,
1.0, 0.0,
0.0, 1.0,
1.0, 1.0,
1.0, 0.0
];
//all entities share the same texture geometry
SEBASTIAN.WEBGL.WORLD.ENTITIES.GLOBALS.vertexPositions=vertexPositions;
SEBASTIAN.WEBGL.WORLD.ENTITIES.GLOBALS.vertexTextureCoords=vertexTextureCoords;
var aVertexTextureCoords=new Float32Array(vertexTextureCoords);
SEBASTIAN.WEBGL.WORLD.ENTITIES.GLOBALS.aVertexTextureCoords=aVertexTextureCoords;
},
add:function(cfg){ //proc add {green indent_4}
cfg=cfg?cfg:{};
var config={
isBot:cfg.isBot || 0,
x:cfg.x || 0,
y:cfg.y || 0,
z:cfg.z || 0,
rx:cfg.rx || 0,
ry:cfg.ry || 0,
rz:cfg.rz || 0,
scale:cfg.scale,
color1:cfg.color1 || [1.0,1.0,1.0],
colorDynamic:cfg.colorDynamic || '', //2018-03-22 12:11:51 allows to color the entity with a color that varies depending on the time
speed:cfg.speed || 0,
textureId:cfg.textureId || 'sel_02',
opacity:cfg.opacity || 1,
isLivingBeing:cfg.isLivingBeing || 0,
isLightEmitter:cfg.isLightEmitter || 0,
hasShadowMitigation:cfg.hasShadowMitigation || 0,
attachToCurrentTile:cfg.attachToCurrentTile || 0,
isFlippedX:cfg.isFlippedX || 0,
};
var _seba=SEBASTIAN;
var worldData=_seba.GLOBALS.worldData;
var newEntityId=worldData.entities.length;
worldData.entities.push(config);
worldData.entities[newEntityId].id=newEntityId;
return newEntityId;
},
bootBot:function(idx,cloneIdx){ //proc bootBot {green indent_4}
var worldData=SEBASTIAN.GLOBALS.worldData;
var currentEntity=worldData.entities[idx];
var resetSingleEntity=false;
if (typeof cloneIdx!=='undefined')
resetSingleEntity=true;
if (typeof currentEntity.isCluster!=='undefined' && currentEntity.isCluster || resetSingleEntity){
if (typeof currentEntity.cloneOf!=='undefined')
currentEntity=worldData.entities[currentEntity.cloneOf]; // take the parent entity of the current clone
var nClones=currentEntity.clusterInfo.clones;
var ooX=currentEntity.clusterInfo.xRange[0];
var ooY=currentEntity.clusterInfo.yRange[0];
var ooZ=currentEntity.clusterInfo.zRange[0];
var yStep=currentEntity.clusterInfo.yStep;
var stepX=(currentEntity.clusterInfo.xRange[1]-currentEntity.clusterInfo.xRange[0])/nClones;
var stepY=(currentEntity.clusterInfo.yRange[1]-currentEntity.clusterInfo.yRange[0])/nClones;
var stepZ=(currentEntity.clusterInfo.zRange[1]-currentEntity.clusterInfo.zRange[0])/nClones;
var xLimit=currentEntity.clusterInfo.xRange[1];
var minSpeed=currentEntity.clusterInfo.speedRange[0];
var maxSpeed=currentEntity.clusterInfo.speedRange[1];
var minY=currentEntity.clusterInfo.yRange[0];
var maxY=currentEntity.clusterInfo.yRange[1];
var minZ=currentEntity.clusterInfo.zRange[0];
var maxZ=currentEntity.clusterInfo.zRange[1];
var minOpacity=currentEntity.clusterInfo.opacityRange[0];
var maxOpacity=currentEntity.clusterInfo.opacityRange[1];
var minScale=currentEntity.clusterInfo.scaleRange[0];
var maxScale=currentEntity.clusterInfo.scaleRange[1];
var behaviorId=currentEntity.clusterInfo.behaviorId;
var clusterScatter=currentEntity.clusterInfo.scatter;
var colors=currentEntity.clusterInfo.colors;
var colorDynamic=currentEntity.colorDynamic;
var isStanding=currentEntity.isStanding;
var colorsPool=currentEntity.clusterInfo.colorsPool;
var isLightEmitter=currentEntity.isLightEmitter;
var isFlippedX=currentEntity.isFlippedX;
var hasShadowMitigation=currentEntity.hasShadowMitigation;
if (typeof clusterScatter==='undefined')
clusterScatter=1;
if (resetSingleEntity)
nClones=1;
for (var z=0,zEnd=nClones;z<zEnd;z++){
//var textureId=currentEntity.clusterInfo.textures[Math.floor(Math.random()*currentEntity.clusterInfo.textures.length)];
var textureId=currentEntity.clusterInfo.textures[Math.floor(Math.random()*currentEntity.clusterInfo.textures.length)];
var speed=(Math.random() * (maxSpeed-minSpeed)) + minSpeed;
var opacity=(Math.random() * (maxOpacity-minOpacity)) + minOpacity;
var scale=(Math.random() * (maxScale-minScale)) + minScale;
//console.log(speed);
ooZ=(Math.random() * (maxZ-minZ)) + minZ;
ooY=(Math.random() * (maxY-minY)) + minY;
if (typeof yStep!=='undefined'){ //per il tronco dell'albero
if (typeof currentEntity.currentAutoY==='undefined')
currentEntity.currentAutoY=currentEntity.clusterInfo.yRange[0];
ooY=currentEntity.currentAutoY;
currentEntity.currentAutoY+=yStep;
}
var newEntityId;
if (!resetSingleEntity){
newEntityId=SEBASTIAN.WEBGL.WORLD.ENTITIES.add({});
SEBASTIAN.GLOBALS.worldData.entities[newEntityId].cloneOf=idx;
}else{
newEntityId=idx;
}
var theEntity=SEBASTIAN.GLOBALS.worldData.entities[newEntityId];
theEntity.behaviorId=behaviorId;
theEntity.isBot=1;
theEntity.x=ooX;
theEntity.y=ooY;
theEntity.z=ooZ;
theEntity.textureId=textureId;
theEntity.oTextureId=theEntity.textureId;
theEntity.speed=speed;
theEntity.opacity=opacity;
theEntity.scale=scale;
theEntity.isIdle=0;
theEntity.isLightEmitter=isLightEmitter;
theEntity.hasShadowMitigation=hasShadowMitigation;
theEntity.isFlippedX=isFlippedX;
if (theEntity.speed!==0)
theEntity.xLimit=xLimit;
if (typeof colors!=='undefined'){
var chosenColor=currentEntity.clusterInfo.colors[Math.floor(Math.random()*currentEntity.clusterInfo.colors.length)];
theEntity.color1=[chosenColor[0]/255,chosenColor[1]/255,chosenColor[2]/255,];
}
if (typeof colorDynamic!=='undefined'){ // 2018-03-22 15:05:03 dynamic color applied to an entire group of clones clusters
var h_key=SEBASTIAN.GLOBALS.hours;
var m_key=SEBASTIAN.GLOBALS.minutes;
var colorKey=h_key+'_'+m_key;
var colorsPoolIdx='p'+colorDynamic;
var chosenColor=SEBASTIAN.GLOBALS.lightColorTimeMap[colorKey][colorsPoolIdx];
theEntity.hasPoolColor=1;
theEntity.colorsPoolIdx=colorsPoolIdx;
theEntity.color1=chosenColor;
}
if (typeof colorsPool!=='undefined'){ // 2018-03-21 01:21:41 select a random color from the corresponding pool
var h_key=SEBASTIAN.GLOBALS.hours;
var m_key=SEBASTIAN.GLOBALS.minutes;
var colorKey=h_key+'_'+m_key;
//get a random value from the color pool
var max=5;
var min=1;
var rnd=Math.floor(Math.random() * (max - min + 1)) + min; //ref: https://stackoverflow.com/questions/1527803/generating-random-whole-numbers-in-javascript-in-a-specific-range
//console.log('p'+colorsPool+rnd);
var colorsPoolIdx='p'+colorsPool+rnd;
var chosenColor=SEBASTIAN.GLOBALS.lightColorTimeMap[colorKey][colorsPoolIdx];
theEntity.hasPoolColor=1;
theEntity.colorsPoolIdx=colorsPoolIdx;
theEntity.color1=chosenColor;
//console.log(theEntity.color1);
}
theEntity.oColor1=theEntity.color1;
//define geometry and stuff
SEBASTIAN.WEBGL.WORLD.ENTITIES.define(newEntityId);
if (clusterScatter){ // if 1 spread the clones around (eg clouds)
ooX+=stepX;
ooY+=stepY;
}
}
}
},
setLivingCreatureBehaviors:function(currentEntity){ //proc setLivingBehaviors {green indent_4}
var _seba=SEBASTIAN;
var h_key=_seba.GLOBALS.hours;
var m_key=_seba.GLOBALS.minutes;
var timeIdx=h_key*60+m_key;
var bedtime_hours=20;
var bedtime_minutes=30;
var waketime_hours=7;
var waketime_minutes=30;
//2018-04-30 19:33:25
// add calculation taking into account daylight saving time and offset
var ddd=new Date();
var offsetHours=ddd.getTimezoneOffset()/60;
bedtime_hours-=-offsetHours;
waketime_hours-=-offsetHours;
//console.log('bed',bedtime_hours,'wake',waketime_hours);
var bedtime_idx =bedtime_hours*60+bedtime_minutes;
var waketime_idx=waketime_hours*60+waketime_minutes;
//set a random bedtime/waketime interval
var max=20;
var min=0;
var rnd=Math.floor(Math.random()*(max-min+1))+min;//https://stackoverflow.com/questions/1527803/generating-random-whole-numbers-in-javascript-in-a-specific-range
currentEntity.bedtime=bedtime_idx+rnd;
var rnd=Math.floor(Math.random()*(max-min+1))+min;
currentEntity.waketime=waketime_idx+rnd;
//console.log('bedtime',currentEntity.bedtime,'waketime',currentEntity.waketime);
if (currentEntity.isAwake===1){ //do not allow to set wake alarms on the past
if (timeIdx<currentEntity.waketime)
currentEntity.waketime=timeIdx-1;
}
},
define:function(idx){ //proc define {green indent_4}
var _seba=SEBASTIAN;
var worldData=_seba.GLOBALS.worldData;
var currentEntity=worldData.entities[idx];
if (typeof currentEntity.isCluster!=='undefined' && currentEntity.isCluster){
_seba.WEBGL.WORLD.ENTITIES.bootBot(idx);
// The cluster is an invisible 'master' that is cloned
currentEntity.isHidden=1;
currentEntity.x=-5000; //'hide' geometry
}else{
// if the entity is not of type cluster,
// create the lookup of entities by name
//console.log(currentEntity.name);
if (typeof currentEntity.name!=='undefined'){
if (typeof currentEntity.isBot==='undefined' || !currentEntity.isBot){
if (typeof worldData.entitiesNamePointer==='undefined')
worldData.entitiesNamePointer={};
worldData.entitiesNamePointer[currentEntity.name]=worldData.entities[idx];
//console.log(currentEntity.name,SEBASTIAN.GLOBALS.worldData.entitiesNamePointer);
}
}
}
if (typeof currentEntity.isStanding==='undefined')
currentEntity.isStanding=1;
if (typeof currentEntity.isLightEmitter==='undefined')
currentEntity.isLightEmitter=0;
if (typeof currentEntity.hasShadowMitigation==='undefined')
currentEntity.hasShadowMitigation=0;
if (typeof currentEntity.isFlippedX==='undefined')
currentEntity.isFlippedX=0;
if (currentEntity.isLivingBeing){
_seba.WEBGL.WORLD.ENTITIES.setLivingCreatureBehaviors(currentEntity);
}
if (typeof currentEntity.colorDynamic!=='undefined' && currentEntity.colorDynamic!==''){ //dDMKCWhHp4
//var tDate=new Date();
//var h_key=tDate.getHours();
//var m_key=tDate.getMinutes();
var h_key=_seba.GLOBALS.hours;
var m_key=_seba.GLOBALS.minutes;
var colorKey=h_key+'_'+m_key;
var colorsPoolIdx='p'+currentEntity.colorDynamic;
//var chosenColor=_seba.GLOBALS.lightColorTimeMap[colorKey][colorsPoolIdx];
currentEntity.hasPoolColor=1;
currentEntity.colorsPoolIdx=colorsPoolIdx;
}
var isFloatingOnWater=0;
//proc geometry animation behavior INIT {yellow indent_5}
switch (currentEntity.behaviorId){
case 1: //taraxacum geometry deform (windflow-like)
var minDeformSpeed=0.00001;
var maxDeformSpeed=0.00003;
var deformSpeed=(Math.random() * (maxDeformSpeed-minDeformSpeed)) + minDeformSpeed;
currentEntity.counterDeltaIncrement=deformSpeed;
break;
case 2: //breath geometry deform (organic-life-like)
var minDeformSpeed=0.00002;
var maxDeformSpeed=0.000025;
var breathDeformLimit=0.05;
if (typeof currentEntity.breatheSpeed_range!=='undefined'){
minDeformSpeed=currentEntity.breatheSpeed_range[0];
maxDeformSpeed=currentEntity.breatheSpeed_range[1];
}
var deformSpeed=(Math.random() * (maxDeformSpeed-minDeformSpeed)) + minDeformSpeed;
if (typeof currentEntity.breathDeformLimit!=='undefined')
breathDeformLimit=currentEntity.breathDeformLimit;
currentEntity.counterDeltaIncrement=deformSpeed;
currentEntity.breathDeformLimit=breathDeformLimit;
if (currentEntity.isFloatingOnWater===1)
isFloatingOnWater=1;
break;
case 3: //water geometry deform (windflow-like)
var minDeformSpeed=0.00003;
var maxDeformSpeed=0.00005;
var deformSpeed=(Math.random() * (maxDeformSpeed-minDeformSpeed)) + minDeformSpeed;
//var deformSpeed=0.0001;
currentEntity.counterDeltaIncrement=deformSpeed;
break;
case 4: // objects that float in the water
isFloatingOnWater=1;
break;
}
if (isFloatingOnWater){
currentEntity.counterDeltaYIncrement=0.000012;
currentEntity.counterYTotalDistance=0.0015;
}
//SEBASTIAN.GLOBALS.worldData.entities[
//console.log(idx,SEBASTIAN.GLOBALS.worldData.entities[idx].scale);
SEBASTIAN.WEBGL.WORLD.ENTITIES.setGeometry(idx);
},
checkEntitiesDepthVisibilityMousePos(updateDepth,updateVisibility,applyMouseDetection){ //proc checkEntitiesDepthVisibilityMousePos {green indent_4}
//cycle on all entities, check their visibility,calculate their depth
//and update the zdepth array
// if updateDepth is 1 updates the position z of all entities
// we need it for
// - reorder the zbuffer if necessary
// - determine the entity under the mouse
// - to determine if an entity is visible (if invisible we do not animate geometry)
var _seba=SEBASTIAN;
var vertexPositions=_seba.WEBGL.GLOBALS.buffers.entitiesVertexPositionsZ.data;
var worldData=_seba.GLOBALS.worldData;
var depths=_seba.WEBGL.WORLD.ENTITIES.GLOBALS.depthSorted;
var xPos =_seba.WEBGL.WORLD.GLOBALS.xPos;
var yPos =_seba.WEBGL.WORLD.GLOBALS.yPos;
var zPos =_seba.WEBGL.WORLD.GLOBALS.zPos;
var pMatrix =_seba.WEBGL.WORLD.GLOBALS.pMatrix;
var mvMatrix =_seba.WEBGL.WORLD.GLOBALS.mvMatrix;
var gl =_seba.GLOBALS.webgl_ctx; //lookup var
var mx=_seba.GLOBALS.mx;
var my=_seba.GLOBALS.my;
var skippedEntities=0;
var foundEntityUnderMouse=0;
for (var z=0,zEnd=worldData.entities.length;z<zEnd;z++){
var currentEntity=worldData.entities[z];
if (updateVisibility){
currentEntity.isVisible=1;
var idx=z*6*3; //the entities have ids based on their creation
if (vertexPositions[idx+2]+currentEntity.z>zPos){
currentEntity.isVisible=0;
skippedEntities++;
}else{
var aa=_seba.WEBGL.project(vertexPositions[idx+0],vertexPositions[idx+1],vertexPositions[idx+2],xPos,yPos,zPos,currentEntity.x,currentEntity.y,currentEntity.z,pMatrix,mvMatrix);
var ff=_seba.WEBGL.project(vertexPositions[idx+15],vertexPositions[idx+16],vertexPositions[idx+17],xPos,yPos,zPos,currentEntity.x,currentEntity.y,currentEntity.z,pMatrix,mvMatrix);
if (ff[0]<-100 || aa[0]>gl.viewportWidth+100 || ff[1]<-100 || aa[1]>gl.viewportHeight+100)
currentEntity.isVisible=0;
}
if (applyMouseDetection && _seba.GLOBALS.isMouseDirty && currentEntity.isVisible){
var ee=_seba.WEBGL.project(vertexPositions[idx+12],vertexPositions[idx+13],vertexPositions[idx+14],xPos,yPos,zPos,currentEntity.x,currentEntity.y,currentEntity.z,pMatrix,mvMatrix);
if (mx>=aa[0] && mx<ee[0]){
if (my>=aa[1] && my<ff[1]){
foundEntityUnderMouse=1;
currentEntity.color1=_seba.GLOBALS.entitySelectionColor;
_seba.WEBGL.WORLD.ENTITIES.syncBuffersData(currentEntity); // since we have changed a property we have to update the buffers
_seba.GLOBALS.currentEntityId=z;
_seba.GLOBALS.isMouseDirty=0;
}
}
}
}
if (updateDepth){
depths[currentEntity.id]={
//make a calculation to determine the z-index of the current Entity
//A bit Approximate but functional. Enough for our simplified 3d simulated world.
//for our simulation simplified 3d
//depth:_seba.WEBGL.getDepth(xPos,yPos,zPos,quat4,currentEntity.x,currentEntity.y,currentEntity.z)
// Performance trick
//if we consider that we will never make particular
//rotations for rendering, we just need to use z as a depth factor ...
depth:currentEntity.z,
entityId:currentEntity.id
};
}
}
if (updateDepth){
depths.sort(function(a,b){ //sort by depth, painter's algorithm.
return a.depth-b.depth;
});
}
if (applyMouseDetection)
return [foundEntityUnderMouse,skippedEntities];
},
sortZBuffersByEntityPosition(){ //proc sortZBuffersByEntityPosition {green indent_4}
//very similar to syncBuffersData but for all entities
//after Z sorting
var _seba=SEBASTIAN;
var worldData=_seba.GLOBALS.worldData;
var depths=_seba.WEBGL.WORLD.ENTITIES.GLOBALS.depthSorted;
var gl =_seba.GLOBALS.webgl_ctx; //lookup var
//we need only the z position of the entities -> exclude the rest
_seba.WEBGL.WORLD.ENTITIES.checkEntitiesDepthVisibilityMousePos(1,0,0);
//var dEntitiesTextureCoords=_seba.WEBGL.GLOBALS.buffers.entitiesTextureCoords.data;
var dEntitiesVertexPositions=_seba.WEBGL.GLOBALS.buffers.entitiesVertexPositions.data;
//var dEntitiesTranslations=_seba.WEBGL.GLOBALS.buffers.entitiesTranslations.data;
//var dEntitiesSpriteColors=_seba.WEBGL.GLOBALS.buffers.entitiesSpriteColors.data;
//var dEntitiesSpriteAlphas=_seba.WEBGL.GLOBALS.buffers.entitiesSpriteAlphas.data;
//--
var dEntitiesTextureCoordsZ=_seba.WEBGL.GLOBALS.buffers.entitiesTextureCoordsZ.data;
var dEntitiesVertexPositionsZ=_seba.WEBGL.GLOBALS.buffers.entitiesVertexPositionsZ.data;
var dEntitiesTranslationsZ=_seba.WEBGL.GLOBALS.buffers.entitiesTranslationsZ.data;
var dEntitiesSpriteColorsZ=_seba.WEBGL.GLOBALS.buffers.entitiesSpriteColorsZ.data;
//var dEntitiesSpriteAlphasZ=_seba.WEBGL.GLOBALS.buffers.entitiesSpriteAlphasZ.data;
//var dEntitiesTextureLayerIndexesZ=_seba.WEBGL.GLOBALS.buffers.entitiesTextureLayerIndexesZ.data;
var dEntitiesPropertiesZ=_seba.WEBGL.GLOBALS.buffers.entitiesPropertiesZ.data;
var dEntitiesVertexPositionsZIdx=0;
var dEntitiesTextureCoordsZIdx=0;
var dEntitiesTranslationsZIdx=0;
var dEntitiesSpriteColorsZIdx=0;
//var dEntitiesSpriteAlphasZIdx=0;
//var dEntitiesTextureLayerIndexesZIdx=0;
var dEntitiesPropertiesZIdx=0;
for (var z=0,zEnd=worldData.entities.length;z<zEnd;z++){
var currentEntity=worldData.entities[depths[z].entityId]; //we obtain the ordered entities based on depth, and we use the painter algorithm to draw them
currentEntity.depthId=z;
//var idx0=currentEntity.id*6;
//var idx2=currentEntity.id*6*2;
var idx3=currentEntity.id*6*3;
var currentTexture=_seba.WEBGL.GLOBALS.textures[currentEntity.textureId];
if (typeof currentTexture==='undefined'){
currentTexture=_seba.WEBGL.GLOBALS.textures['pavement_01'];
//console.log(currentEntity.oTextureId,'->','pavement_01');
}
//texture coordinates (2 points per vertex)
dEntitiesTextureCoordsZ[dEntitiesTextureCoordsZIdx+0]=currentTexture.textureCoordinates[0];
dEntitiesTextureCoordsZ[dEntitiesTextureCoordsZIdx+1]=currentTexture.textureCoordinates[1];
dEntitiesTextureCoordsZ[dEntitiesTextureCoordsZIdx+2]=currentTexture.textureCoordinates[2];
dEntitiesTextureCoordsZ[dEntitiesTextureCoordsZIdx+3]=currentTexture.textureCoordinates[3];
dEntitiesTextureCoordsZ[dEntitiesTextureCoordsZIdx+4]=currentTexture.textureCoordinates[4];
dEntitiesTextureCoordsZ[dEntitiesTextureCoordsZIdx+5]=currentTexture.textureCoordinates[5];
dEntitiesTextureCoordsZ[dEntitiesTextureCoordsZIdx+6]=currentTexture.textureCoordinates[6];
dEntitiesTextureCoordsZ[dEntitiesTextureCoordsZIdx+7]=currentTexture.textureCoordinates[7];
dEntitiesTextureCoordsZ[dEntitiesTextureCoordsZIdx+8]=currentTexture.textureCoordinates[8];
dEntitiesTextureCoordsZ[dEntitiesTextureCoordsZIdx+9]=currentTexture.textureCoordinates[9];
dEntitiesTextureCoordsZ[dEntitiesTextureCoordsZIdx+10]=currentTexture.textureCoordinates[10];
dEntitiesTextureCoordsZ[dEntitiesTextureCoordsZIdx+11]=currentTexture.textureCoordinates[11];
dEntitiesTextureCoordsZIdx+=12;
//vertex positions (3 points per vertex)
dEntitiesVertexPositionsZ[dEntitiesVertexPositionsZIdx+0]=dEntitiesVertexPositions[idx3+0];
dEntitiesVertexPositionsZ[dEntitiesVertexPositionsZIdx+1]=dEntitiesVertexPositions[idx3+1];
dEntitiesVertexPositionsZ[dEntitiesVertexPositionsZIdx+2]=dEntitiesVertexPositions[idx3+2];
dEntitiesVertexPositionsZ[dEntitiesVertexPositionsZIdx+3]=dEntitiesVertexPositions[idx3+3];
dEntitiesVertexPositionsZ[dEntitiesVertexPositionsZIdx+4]=dEntitiesVertexPositions[idx3+4];
dEntitiesVertexPositionsZ[dEntitiesVertexPositionsZIdx+5]=dEntitiesVertexPositions[idx3+5];
dEntitiesVertexPositionsZ[dEntitiesVertexPositionsZIdx+6]=dEntitiesVertexPositions[idx3+6];
dEntitiesVertexPositionsZ[dEntitiesVertexPositionsZIdx+7]=dEntitiesVertexPositions[idx3+7];
dEntitiesVertexPositionsZ[dEntitiesVertexPositionsZIdx+8]=dEntitiesVertexPositions[idx3+8];
dEntitiesVertexPositionsZ[dEntitiesVertexPositionsZIdx+9]=dEntitiesVertexPositions[idx3+9];
dEntitiesVertexPositionsZ[dEntitiesVertexPositionsZIdx+10]=dEntitiesVertexPositions[idx3+10];
dEntitiesVertexPositionsZ[dEntitiesVertexPositionsZIdx+11]=dEntitiesVertexPositions[idx3+11];
dEntitiesVertexPositionsZ[dEntitiesVertexPositionsZIdx+12]=dEntitiesVertexPositions[idx3+12];
dEntitiesVertexPositionsZ[dEntitiesVertexPositionsZIdx+13]=dEntitiesVertexPositions[idx3+13];
dEntitiesVertexPositionsZ[dEntitiesVertexPositionsZIdx+14]=dEntitiesVertexPositions[idx3+14];
dEntitiesVertexPositionsZ[dEntitiesVertexPositionsZIdx+15]=dEntitiesVertexPositions[idx3+15];
dEntitiesVertexPositionsZ[dEntitiesVertexPositionsZIdx+16]=dEntitiesVertexPositions[idx3+16];
dEntitiesVertexPositionsZ[dEntitiesVertexPositionsZIdx+17]=dEntitiesVertexPositions[idx3+17];
dEntitiesVertexPositionsZIdx+=18;
//vertex translations (3 points per vertex)
dEntitiesTranslationsZ[dEntitiesTranslationsZIdx+0]=currentEntity.x;
dEntitiesTranslationsZ[dEntitiesTranslationsZIdx+1]=currentEntity.y;
dEntitiesTranslationsZ[dEntitiesTranslationsZIdx+2]=currentEntity.z;
dEntitiesTranslationsZ[dEntitiesTranslationsZIdx+3]=currentEntity.x;
dEntitiesTranslationsZ[dEntitiesTranslationsZIdx+4]=currentEntity.y;
dEntitiesTranslationsZ[dEntitiesTranslationsZIdx+5]=currentEntity.z;
dEntitiesTranslationsZ[dEntitiesTranslationsZIdx+6]=currentEntity.x;
dEntitiesTranslationsZ[dEntitiesTranslationsZIdx+7]=currentEntity.y;
dEntitiesTranslationsZ[dEntitiesTranslationsZIdx+8]=currentEntity.z;
dEntitiesTranslationsZ[dEntitiesTranslationsZIdx+9]=currentEntity.x;
dEntitiesTranslationsZ[dEntitiesTranslationsZIdx+10]=currentEntity.y;
dEntitiesTranslationsZ[dEntitiesTranslationsZIdx+11]=currentEntity.z;
dEntitiesTranslationsZ[dEntitiesTranslationsZIdx+12]=currentEntity.x;
dEntitiesTranslationsZ[dEntitiesTranslationsZIdx+13]=currentEntity.y;
dEntitiesTranslationsZ[dEntitiesTranslationsZIdx+14]=currentEntity.z;
dEntitiesTranslationsZ[dEntitiesTranslationsZIdx+15]=currentEntity.x;
dEntitiesTranslationsZ[dEntitiesTranslationsZIdx+16]=currentEntity.y;
dEntitiesTranslationsZ[dEntitiesTranslationsZIdx+17]=currentEntity.z;
dEntitiesTranslationsZIdx+=18;
//vertex colors (4 points per vertex)
dEntitiesSpriteColorsZ[dEntitiesSpriteColorsZIdx+0]=currentEntity.color1[0];
dEntitiesSpriteColorsZ[dEntitiesSpriteColorsZIdx+1]=currentEntity.color1[1];
dEntitiesSpriteColorsZ[dEntitiesSpriteColorsZIdx+2]=currentEntity.color1[2];
dEntitiesSpriteColorsZ[dEntitiesSpriteColorsZIdx+3]=currentEntity.opacity;
dEntitiesSpriteColorsZ[dEntitiesSpriteColorsZIdx+4]=currentEntity.color1[0];
dEntitiesSpriteColorsZ[dEntitiesSpriteColorsZIdx+5]=currentEntity.color1[1];
dEntitiesSpriteColorsZ[dEntitiesSpriteColorsZIdx+6]=currentEntity.color1[2];
dEntitiesSpriteColorsZ[dEntitiesSpriteColorsZIdx+7]=currentEntity.opacity;
dEntitiesSpriteColorsZ[dEntitiesSpriteColorsZIdx+8]=currentEntity.color1[0];
dEntitiesSpriteColorsZ[dEntitiesSpriteColorsZIdx+9]=currentEntity.color1[1];
dEntitiesSpriteColorsZ[dEntitiesSpriteColorsZIdx+10]=currentEntity.color1[2];
dEntitiesSpriteColorsZ[dEntitiesSpriteColorsZIdx+11]=currentEntity.opacity;
dEntitiesSpriteColorsZ[dEntitiesSpriteColorsZIdx+12]=currentEntity.color1[0];
dEntitiesSpriteColorsZ[dEntitiesSpriteColorsZIdx+13]=currentEntity.color1[1];
dEntitiesSpriteColorsZ[dEntitiesSpriteColorsZIdx+14]=currentEntity.color1[2];
dEntitiesSpriteColorsZ[dEntitiesSpriteColorsZIdx+15]=currentEntity.opacity;
dEntitiesSpriteColorsZ[dEntitiesSpriteColorsZIdx+16]=currentEntity.color1[0];
dEntitiesSpriteColorsZ[dEntitiesSpriteColorsZIdx+17]=currentEntity.color1[1];
dEntitiesSpriteColorsZ[dEntitiesSpriteColorsZIdx+18]=currentEntity.color1[2];
dEntitiesSpriteColorsZ[dEntitiesSpriteColorsZIdx+19]=currentEntity.opacity;
dEntitiesSpriteColorsZ[dEntitiesSpriteColorsZIdx+20]=currentEntity.color1[0];
dEntitiesSpriteColorsZ[dEntitiesSpriteColorsZIdx+21]=currentEntity.color1[1];
dEntitiesSpriteColorsZ[dEntitiesSpriteColorsZIdx+22]=currentEntity.color1[2];
dEntitiesSpriteColorsZ[dEntitiesSpriteColorsZIdx+23]=currentEntity.opacity;
dEntitiesSpriteColorsZIdx+=24;
dEntitiesPropertiesZ[ dEntitiesPropertiesZIdx]=currentTexture.oX;
dEntitiesPropertiesZ[++dEntitiesPropertiesZIdx]=currentTexture.layerId;
//pack flags
//http://theinstructionlimit.com/encoding-boolean-flags-into-a-float-in-hlsl
dEntitiesPropertiesZ[++dEntitiesPropertiesZIdx]=currentTexture.textureCoordinates[4];
//proc ENTITIES.PROPERTIES.FLAGS {violet bold indent_5}
// the properties are mutually exclusive
dEntitiesPropertiesZ[++dEntitiesPropertiesZIdx]=currentEntity.hasShadowMitigation+10*currentEntity.isLightEmitter+20*currentEntity.isFlippedX;
//--
dEntitiesPropertiesZ[++dEntitiesPropertiesZIdx]=currentTexture.oX;
dEntitiesPropertiesZ[++dEntitiesPropertiesZIdx]=currentTexture.layerId;
dEntitiesPropertiesZ[++dEntitiesPropertiesZIdx]=currentTexture.textureCoordinates[4];
dEntitiesPropertiesZ[++dEntitiesPropertiesZIdx]=currentEntity.hasShadowMitigation+10*currentEntity.isLightEmitter+20*currentEntity.isFlippedX;
//--
dEntitiesPropertiesZ[++dEntitiesPropertiesZIdx]=currentTexture.oX;
dEntitiesPropertiesZ[++dEntitiesPropertiesZIdx]=currentTexture.layerId;
dEntitiesPropertiesZ[++dEntitiesPropertiesZIdx]=currentTexture.textureCoordinates[4];
dEntitiesPropertiesZ[++dEntitiesPropertiesZIdx]=currentEntity.hasShadowMitigation+10*currentEntity.isLightEmitter+20*currentEntity.isFlippedX;
//--
dEntitiesPropertiesZ[++dEntitiesPropertiesZIdx]=currentTexture.oX;
dEntitiesPropertiesZ[++dEntitiesPropertiesZIdx]=currentTexture.layerId;
dEntitiesPropertiesZ[++dEntitiesPropertiesZIdx]=currentTexture.textureCoordinates[4];
dEntitiesPropertiesZ[++dEntitiesPropertiesZIdx]=currentEntity.hasShadowMitigation+10*currentEntity.isLightEmitter+20*currentEntity.isFlippedX;
//--
dEntitiesPropertiesZ[++dEntitiesPropertiesZIdx]=currentTexture.oX;
dEntitiesPropertiesZ[++dEntitiesPropertiesZIdx]=currentTexture.layerId;
dEntitiesPropertiesZ[++dEntitiesPropertiesZIdx]=currentTexture.textureCoordinates[4];
dEntitiesPropertiesZ[++dEntitiesPropertiesZIdx]=currentEntity.hasShadowMitigation+10*currentEntity.isLightEmitter+20*currentEntity.isFlippedX;
//--
dEntitiesPropertiesZ[++dEntitiesPropertiesZIdx]=currentTexture.oX;
dEntitiesPropertiesZ[++dEntitiesPropertiesZIdx]=currentTexture.layerId;
dEntitiesPropertiesZ[++dEntitiesPropertiesZIdx]=currentTexture.textureCoordinates[4];
dEntitiesPropertiesZ[++dEntitiesPropertiesZIdx]=currentEntity.hasShadowMitigation+10*currentEntity.isLightEmitter+20*currentEntity.isFlippedX;
dEntitiesPropertiesZIdx++;
}
gl.bindBuffer(gl.ARRAY_BUFFER,_seba.WEBGL.GLOBALS.buffers.entitiesPropertiesZ.buffer);
gl.bufferData(gl.ARRAY_BUFFER,dEntitiesPropertiesZ,gl.DYNAMIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER,_seba.WEBGL.GLOBALS.buffers.entitiesSpriteColorsZ.buffer);
gl.bufferData(gl.ARRAY_BUFFER,dEntitiesSpriteColorsZ,gl.DYNAMIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER,_seba.WEBGL.GLOBALS.buffers.entitiesTranslationsZ.buffer);
gl.bufferData(gl.ARRAY_BUFFER,dEntitiesTranslationsZ,gl.DYNAMIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER,_seba.WEBGL.GLOBALS.buffers.entitiesVertexPositionsZ.buffer);
gl.bufferData(gl.ARRAY_BUFFER,dEntitiesVertexPositionsZ,gl.DYNAMIC_DRAW);
gl.bindBuffer(gl.ARRAY_BUFFER,_seba.WEBGL.GLOBALS.buffers.entitiesTextureCoordsZ.buffer);
gl.bufferData(gl.ARRAY_BUFFER,dEntitiesTextureCoordsZ,gl.DYNAMIC_DRAW);
},
syncBuffersData:function(currentEntity){ //proc syncBuffersData {green indent_4}
//since we have abandoned the simplicity of having a drawcall
//for each entity I am forced to update all the buffers to keep
//the properties of the entity coupled to the data that are used by opengl to draw it
//we synchronize the Zbuffers according to the entity status
var _seba=SEBASTIAN;
var gl =_seba.GLOBALS.webgl_ctx; //lookup var
var zIdx0 =currentEntity.depthId*6;
var zIdx2 =currentEntity.depthId*6*2;
var zIdx3 =currentEntity.depthId*6*3;
var zIdx4 =currentEntity.depthId*6*4; //2018-05-03 17:20:45
//console.log(_seba.WEBGL.WORLD.ENTITIES.GLOBALS.totalProperties);
var zIdxProp=currentEntity.depthId*6*_seba.WEBGL.WORLD.ENTITIES.GLOBALS.totalProperties;
//--
var dEntitiesTextureCoordsZ=_seba.WEBGL.GLOBALS.buffers.entitiesTextureCoordsZ.data;
var dEntitiesTranslationsZ=_seba.WEBGL.GLOBALS.buffers.entitiesTranslationsZ.data;
var dEntitiesSpriteColorsZ=_seba.WEBGL.GLOBALS.buffers.entitiesSpriteColorsZ.data;
var dEntitiesPropertiesZ=_seba.WEBGL.GLOBALS.buffers.entitiesPropertiesZ.data;
var currentTexture=_seba.WEBGL.GLOBALS.textures[currentEntity.textureId];
if (typeof currentTexture==='undefined'){
currentTexture=_seba.WEBGL.GLOBALS.textures['pavement_01'];
//console.log(currentEntity.oTextureId,'->','pavement_01');
}
dEntitiesTextureCoordsZ[zIdx2+0]=currentTexture.textureCoordinates[0];
dEntitiesTextureCoordsZ[zIdx2+1]=currentTexture.textureCoordinates[1];
dEntitiesTextureCoordsZ[zIdx2+2]=currentTexture.textureCoordinates[2];
dEntitiesTextureCoordsZ[zIdx2+3]=currentTexture.textureCoordinates[3];
dEntitiesTextureCoordsZ[zIdx2+4]=currentTexture.textureCoordinates[4];
dEntitiesTextureCoordsZ[zIdx2+5]=currentTexture.textureCoordinates[5];
dEntitiesTextureCoordsZ[zIdx2+6]=currentTexture.textureCoordinates[6];
dEntitiesTextureCoordsZ[zIdx2+7]=currentTexture.textureCoordinates[7];
dEntitiesTextureCoordsZ[zIdx2+8]=currentTexture.textureCoordinates[8];
dEntitiesTextureCoordsZ[zIdx2+9]=currentTexture.textureCoordinates[9];
dEntitiesTextureCoordsZ[zIdx2+10]=currentTexture.textureCoordinates[10];
dEntitiesTextureCoordsZ[zIdx2+11]=currentTexture.textureCoordinates[11];
//vertex translations (3 points per vertex)
dEntitiesTranslationsZ[zIdx3+0]=currentEntity.x;
dEntitiesTranslationsZ[zIdx3+1]=currentEntity.y;
dEntitiesTranslationsZ[zIdx3+2]=currentEntity.z;
dEntitiesTranslationsZ[zIdx3+3]=currentEntity.x;
dEntitiesTranslationsZ[zIdx3+4]=currentEntity.y;
dEntitiesTranslationsZ[zIdx3+5]=currentEntity.z;
dEntitiesTranslationsZ[zIdx3+6]=currentEntity.x;
dEntitiesTranslationsZ[zIdx3+7]=currentEntity.y;
dEntitiesTranslationsZ[zIdx3+8]=currentEntity.z;
dEntitiesTranslationsZ[zIdx3+9]=currentEntity.x;
dEntitiesTranslationsZ[zIdx3+10]=currentEntity.y;
dEntitiesTranslationsZ[zIdx3+11]=currentEntity.z;
dEntitiesTranslationsZ[zIdx3+12]=currentEntity.x;
dEntitiesTranslationsZ[zIdx3+13]=currentEntity.y;
dEntitiesTranslationsZ[zIdx3+14]=currentEntity.z;
dEntitiesTranslationsZ[zIdx3+15]=currentEntity.x;
dEntitiesTranslationsZ[zIdx3+16]=currentEntity.y;
dEntitiesTranslationsZ[zIdx3+17]=currentEntity.z;
//vertex colors (3 points per vertex)
dEntitiesSpriteColorsZ[zIdx4+0]=currentEntity.color1[0];
dEntitiesSpriteColorsZ[zIdx4+1]=currentEntity.color1[1];
dEntitiesSpriteColorsZ[zIdx4+2]=currentEntity.color1[2];
dEntitiesSpriteColorsZ[zIdx4+3]=currentEntity.opacity;
dEntitiesSpriteColorsZ[zIdx4+4]=currentEntity.color1[0];
dEntitiesSpriteColorsZ[zIdx4+5]=currentEntity.color1[1];
dEntitiesSpriteColorsZ[zIdx4+6]=currentEntity.color1[2];
dEntitiesSpriteColorsZ[zIdx4+7]=currentEntity.opacity;
dEntitiesSpriteColorsZ[zIdx4+8]=currentEntity.color1[0];
dEntitiesSpriteColorsZ[zIdx4+9]=currentEntity.color1[1];
dEntitiesSpriteColorsZ[zIdx4+10]=currentEntity.color1[2];
dEntitiesSpriteColorsZ[zIdx4+11]=currentEntity.opacity;
dEntitiesSpriteColorsZ[zIdx4+12]=currentEntity.color1[0];
dEntitiesSpriteColorsZ[zIdx4+13]=currentEntity.color1[1];
dEntitiesSpriteColorsZ[zIdx4+14]=currentEntity.color1[2];
dEntitiesSpriteColorsZ[zIdx4+15]=currentEntity.opacity;
dEntitiesSpriteColorsZ[zIdx4+16]=currentEntity.color1[0];
dEntitiesSpriteColorsZ[zIdx4+17]=currentEntity.color1[1];
dEntitiesSpriteColorsZ[zIdx4+18]=currentEntity.color1[2];
dEntitiesSpriteColorsZ[zIdx4+19]=currentEntity.opacity;
dEntitiesSpriteColorsZ[zIdx4+20]=currentEntity.color1[0];
dEntitiesSpriteColorsZ[zIdx4+21]=currentEntity.color1[1];
dEntitiesSpriteColorsZ[zIdx4+22]=currentEntity.color1[2];
dEntitiesSpriteColorsZ[zIdx4+23]=currentEntity.opacity;
dEntitiesPropertiesZ[ zIdxProp]=currentTexture.oX;
dEntitiesPropertiesZ[++zIdxProp]=currentTexture.layerId;
//proc ENTITIES.PROPERTIES.FLAGS {violet bold indent_5}
dEntitiesPropertiesZ[++zIdxProp]=currentTexture.textureCoordinates[4];//currentEntity.isLightEmitter;
//console.log(currentEntity.hasShadowMitigation+10*currentEntity.isLightEmitter+20*currentEntity.isFlippedX);
dEntitiesPropertiesZ[++zIdxProp]=currentEntity.hasShadowMitigation+10*currentEntity.isLightEmitter+20*currentEntity.isFlippedX; //poors man bitwise...
//--
dEntitiesPropertiesZ[++zIdxProp]=currentTexture.oX;
dEntitiesPropertiesZ[++zIdxProp]=currentTexture.layerId;
dEntitiesPropertiesZ[++zIdxProp]=currentTexture.textureCoordinates[4];//currentEntity.isLightEmitter;
dEntitiesPropertiesZ[++zIdxProp]=currentEntity.hasShadowMitigation+10*currentEntity.isLightEmitter+20*currentEntity.isFlippedX;
//--
dEntitiesPropertiesZ[++zIdxProp]=currentTexture.oX;
dEntitiesPropertiesZ[++zIdxProp]=currentTexture.layerId;
dEntitiesPropertiesZ[++zIdxProp]=currentTexture.textureCoordinates[4];//currentEntity.isLightEmitter;
dEntitiesPropertiesZ[++zIdxProp]=currentEntity.hasShadowMitigation+10*currentEntity.isLightEmitter+20*currentEntity.isFlippedX;
//--
dEntitiesPropertiesZ[++zIdxProp]=currentTexture.oX;
dEntitiesPropertiesZ[++zIdxProp]=currentTexture.layerId;
dEntitiesPropertiesZ[++zIdxProp]=currentTexture.textureCoordinates[4];//currentEntity.isLightEmitter;
dEntitiesPropertiesZ[++zIdxProp]=currentEntity.hasShadowMitigation+10*currentEntity.isLightEmitter+20*currentEntity.isFlippedX;
//--
dEntitiesPropertiesZ[++zIdxProp]=currentTexture.oX;
dEntitiesPropertiesZ[++zIdxProp]=currentTexture.layerId;
dEntitiesPropertiesZ[++zIdxProp]=currentTexture.textureCoordinates[4];//currentEntity.isLightEmitter;
dEntitiesPropertiesZ[++zIdxProp]=currentEntity.hasShadowMitigation+10*currentEntity.isLightEmitter+20*currentEntity.isFlippedX;
//--
dEntitiesPropertiesZ[++zIdxProp]=currentTexture.oX;
dEntitiesPropertiesZ[++zIdxProp]=currentTexture.layerId;
dEntitiesPropertiesZ[++zIdxProp]=currentTexture.textureCoordinates[4];//currentEntity.isLightEmitter;
dEntitiesPropertiesZ[++zIdxProp]=currentEntity.hasShadowMitigation+10*currentEntity.isLightEmitter+20*currentEntity.isFlippedX;
},
setScale:function(currentEntity){ //proc setScale {green indent_4}
var _seba=SEBASTIAN;
var entitiesVertPosZdata=_seba.WEBGL.GLOBALS.buffers.entitiesVertexPositionsZ.data;
var entitiesVertPosdata=_seba.WEBGL.GLOBALS.buffers.entitiesVertexPositions.data;
var currentEntityVertexZIndex=currentEntity.depthId*6*3;
var currentEntityVertexIndex=currentEntity.id*6*3;
//--
var currentTexture=_seba.WEBGL.GLOBALS.textures[currentEntity.textureId];
if (typeof currentTexture==='undefined'){
currentTexture=_seba.WEBGL.GLOBALS.textures['pavement_01'];
//console.log(currentEntity.oTextureId,'->','pavement_01');
}
//console.log(currentEntity.scale);
if (currentEntity.isStanding===1){
entitiesVertPosdata[currentEntityVertexIndex+0]=0.0*currentEntity.scale*currentTexture.scaleX;
entitiesVertPosdata[currentEntityVertexIndex+1]=1.0*currentEntity.scale*currentTexture.scaleY;
entitiesVertPosdata[currentEntityVertexIndex+2]=0.0;
entitiesVertPosdata[currentEntityVertexIndex+3]=0.0*currentEntity.scale*currentTexture.scaleX;
entitiesVertPosdata[currentEntityVertexIndex+4]=0.0*currentEntity.scale*currentTexture.scaleY;
entitiesVertPosdata[currentEntityVertexIndex+5]=0.0;
entitiesVertPosdata[currentEntityVertexIndex+6]=1.0*currentEntity.scale*currentTexture.scaleX;
entitiesVertPosdata[currentEntityVertexIndex+7]=0.0*currentEntity.scale*currentTexture.scaleY;
entitiesVertPosdata[currentEntityVertexIndex+8]=0.0;
entitiesVertPosdata[currentEntityVertexIndex+9] =0.0*currentEntity.scale*currentTexture.scaleX;
entitiesVertPosdata[currentEntityVertexIndex+10]=1.0*currentEntity.scale*currentTexture.scaleY;
entitiesVertPosdata[currentEntityVertexIndex+11]=0.0;
entitiesVertPosdata[currentEntityVertexIndex+12]=1.0*currentEntity.scale*currentTexture.scaleX;
entitiesVertPosdata[currentEntityVertexIndex+13]=1.0*currentEntity.scale*currentTexture.scaleY;
entitiesVertPosdata[currentEntityVertexIndex+14]=0.0;
entitiesVertPosdata[currentEntityVertexIndex+15]=1.0*currentEntity.scale*currentTexture.scaleX;
entitiesVertPosdata[currentEntityVertexIndex+16]=0.0*currentEntity.scale*currentTexture.scaleY;
entitiesVertPosdata[currentEntityVertexIndex+17]=0.0;
//--
entitiesVertPosZdata[currentEntityVertexZIndex+0]=entitiesVertPosdata[currentEntityVertexIndex];
entitiesVertPosZdata[currentEntityVertexZIndex+1]=entitiesVertPosdata[currentEntityVertexIndex+1];
entitiesVertPosZdata[currentEntityVertexZIndex+2]=entitiesVertPosdata[currentEntityVertexIndex+2];
entitiesVertPosZdata[currentEntityVertexZIndex+3]=entitiesVertPosdata[currentEntityVertexIndex+3];
entitiesVertPosZdata[currentEntityVertexZIndex+4]=entitiesVertPosdata[currentEntityVertexIndex+4];
entitiesVertPosZdata[currentEntityVertexZIndex+5]=entitiesVertPosdata[currentEntityVertexIndex+5];
entitiesVertPosZdata[currentEntityVertexZIndex+6]=entitiesVertPosdata[currentEntityVertexIndex+6];
entitiesVertPosZdata[currentEntityVertexZIndex+7]=entitiesVertPosdata[currentEntityVertexIndex+7];
entitiesVertPosZdata[currentEntityVertexZIndex+8]=entitiesVertPosdata[currentEntityVertexIndex+8];
entitiesVertPosZdata[currentEntityVertexZIndex+9] =entitiesVertPosdata[currentEntityVertexIndex+9];
entitiesVertPosZdata[currentEntityVertexZIndex+10]=entitiesVertPosdata[currentEntityVertexIndex+10];
entitiesVertPosZdata[currentEntityVertexZIndex+11]=entitiesVertPosdata[currentEntityVertexIndex+11];
entitiesVertPosZdata[currentEntityVertexZIndex+12]=entitiesVertPosdata[currentEntityVertexIndex+12];
entitiesVertPosZdata[currentEntityVertexZIndex+13]=entitiesVertPosdata[currentEntityVertexIndex+13];
entitiesVertPosZdata[currentEntityVertexZIndex+14]=entitiesVertPosdata[currentEntityVertexIndex+14];
entitiesVertPosZdata[currentEntityVertexZIndex+15]=entitiesVertPosdata[currentEntityVertexIndex+15];
entitiesVertPosZdata[currentEntityVertexZIndex+16]=entitiesVertPosdata[currentEntityVertexIndex+16];
entitiesVertPosZdata[currentEntityVertexZIndex+17]=entitiesVertPosdata[currentEntityVertexIndex+17];
//if (currentEntity.oTextureId.indexOf('grass')!==-1){
// console.log(currentEntity.oTextureId,currentEntity.scale,currentTexture.scaleX);
//}
}else{ // entity such as water
entitiesVertPosdata[currentEntityVertexIndex+0]=0.0;
entitiesVertPosdata[currentEntityVertexIndex+1]=0.0;
entitiesVertPosdata[currentEntityVertexIndex+2]=0.0;
entitiesVertPosdata[currentEntityVertexIndex+3]=0.0;
entitiesVertPosdata[currentEntityVertexIndex+4]=0.0;
entitiesVertPosdata[currentEntityVertexIndex+5]=1.0*currentEntity.scale*currentTexture.scaleY;
entitiesVertPosdata[currentEntityVertexIndex+6]=1.0*currentEntity.scale*currentTexture.scaleX;
entitiesVertPosdata[currentEntityVertexIndex+7]=0.0;
entitiesVertPosdata[currentEntityVertexIndex+8]=1.0*currentEntity.scale*currentTexture.scaleY;;
entitiesVertPosdata[currentEntityVertexIndex+9] =0.0;
entitiesVertPosdata[currentEntityVertexIndex+10]=0.0;
entitiesVertPosdata[currentEntityVertexIndex+11]=0.0;
entitiesVertPosdata[currentEntityVertexIndex+12]=1.0*currentEntity.scale*currentTexture.scaleX;
entitiesVertPosdata[currentEntityVertexIndex+13]=0.0;
entitiesVertPosdata[currentEntityVertexIndex+14]=0.0;
entitiesVertPosdata[currentEntityVertexIndex+15]=1.0*currentEntity.scale*currentTexture.scaleX;
entitiesVertPosdata[currentEntityVertexIndex+16]=0.0;
entitiesVertPosdata[currentEntityVertexIndex+17]=1.0*currentEntity.scale*currentTexture.scaleY;
//--------
entitiesVertPosZdata[currentEntityVertexZIndex+0]=entitiesVertPosdata[currentEntityVertexIndex];
entitiesVertPosZdata[currentEntityVertexZIndex+1]=entitiesVertPosdata[currentEntityVertexIndex+1];
entitiesVertPosZdata[currentEntityVertexZIndex+2]=entitiesVertPosdata[currentEntityVertexIndex+2];
entitiesVertPosZdata[currentEntityVertexZIndex+3]=entitiesVertPosdata[currentEntityVertexIndex+3];
entitiesVertPosZdata[currentEntityVertexZIndex+4]=entitiesVertPosdata[currentEntityVertexIndex+4];
entitiesVertPosZdata[currentEntityVertexZIndex+5]=entitiesVertPosdata[currentEntityVertexIndex+5];
entitiesVertPosZdata[currentEntityVertexZIndex+6]=entitiesVertPosdata[currentEntityVertexIndex+6];
entitiesVertPosZdata[currentEntityVertexZIndex+7]=entitiesVertPosdata[currentEntityVertexIndex+7];
entitiesVertPosZdata[currentEntityVertexZIndex+8]=entitiesVertPosdata[currentEntityVertexIndex+8];
entitiesVertPosZdata[currentEntityVertexZIndex+9] =entitiesVertPosdata[currentEntityVertexIndex+9];
entitiesVertPosZdata[currentEntityVertexZIndex+10]=entitiesVertPosdata[currentEntityVertexIndex+10];
entitiesVertPosZdata[currentEntityVertexZIndex+11]=entitiesVertPosdata[currentEntityVertexIndex+11];
entitiesVertPosZdata[currentEntityVertexZIndex+12]=entitiesVertPosdata[currentEntityVertexIndex+12];
entitiesVertPosZdata[currentEntityVertexZIndex+13]=entitiesVertPosdata[currentEntityVertexIndex+13];
entitiesVertPosZdata[currentEntityVertexZIndex+14]=entitiesVertPosdata[currentEntityVertexIndex+14];
entitiesVertPosZdata[currentEntityVertexZIndex+15]=entitiesVertPosdata[currentEntityVertexIndex+15];
entitiesVertPosZdata[currentEntityVertexZIndex+16]=entitiesVertPosdata[currentEntityVertexIndex+16];
entitiesVertPosZdata[currentEntityVertexZIndex+17]=entitiesVertPosdata[currentEntityVertexIndex+17];
}
},
animate:function(idx,delta,timeIdx){ //proc animate {green indent_4}
var worldData=SEBASTIAN.GLOBALS.worldData;
var currentEntity=worldData.entities[idx];
var _seba=SEBASTIAN;
var currentEntityVertexZIndex=currentEntity.depthId*6*3; // index of the first vertex of the entity in the zbuffer array
//behavior
//sleep animation
if (currentEntity.isLivingBeing){
if (currentEntity.currentAnimation!=='sleep'){
if (timeIdx>=currentEntity.bedtime || timeIdx<=currentEntity.waketime){
currentEntity.currentAnimation='sleep';
currentEntity.currentAnimationFrameIdx=0;
currentEntity.isPlayingAnim=1;
currentEntity.hasEnteredFrame=0;
currentEntity.saved_textureId=currentEntity.oTextureId; // save the current texture
currentEntity.isAwake=0;
//console.log(currentEntity.name,'is sleeping at',currentEntity.bedtime);
}
}else{
if (currentEntity.isAwake===0){
if (timeIdx>currentEntity.waketime && timeIdx<currentEntity.bedtime){
currentEntity.isPlayingAnim=0;
currentEntity.isAwake=1;
currentEntity.textureId=currentEntity.oTextureId; // save the current texture
//console.log(timeIdx,1440-timeIdx,currentEntity.waketime,currentEntity.bedtime,currentEntity.name,'is awake');
//set random sleep/wake time
SEBASTIAN.WEBGL.WORLD.ENTITIES.setLivingCreatureBehaviors(currentEntity);
//console.log(currentEntity.name,'is awake at',currentEntity.waketime);
}
}
}
}
//movement
//speed X animation
//---------------
if (currentEntity.speed!==0){ // We update the x position only if the speed of the entity is different from 0 (clouds)
currentEntity.x+=currentEntity.speed*delta;
_seba.WEBGL.GLOBALS.buffers.entitiesTranslationsZ.data[currentEntityVertexZIndex+0]=currentEntity.x;
//_seba.WEBGL.GLOBALS.buffers.entitiesTranslations.data[currentEntity.id*6*3+1]=currentEntity.x;
//_seba.WEBGL.GLOBALS.buffers.entitiesTranslations.data[currentEntity.id*6*3+2]=currentEntity.x;
_seba.WEBGL.GLOBALS.buffers.entitiesTranslationsZ.data[currentEntityVertexZIndex+3]=currentEntity.x;
//_seba.WEBGL.GLOBALS.buffers.entitiesTranslations.data[currentEntity.id*6*3+4]=currentEntity.x;
//_seba.WEBGL.GLOBALS.buffers.entitiesTranslations.data[currentEntity.id*6*3+5]=currentEntity.x;
_seba.WEBGL.GLOBALS.buffers.entitiesTranslationsZ.data[currentEntityVertexZIndex+6]=currentEntity.x;
//_seba.WEBGL.GLOBALS.buffers.entitiesTranslations.data[currentEntity.id*6*3+7]=currentEntity.x;
//_seba.WEBGL.GLOBALS.buffers.entitiesTranslations.data[currentEntity.id*6*3+8]=currentEntity.x;
_seba.WEBGL.GLOBALS.buffers.entitiesTranslationsZ.data[currentEntityVertexZIndex+9]=currentEntity.x;
//_seba.WEBGL.GLOBALS.buffers.entitiesTranslations.data[currentEntity.id*6*3+10]=currentEntity.x;
//_seba.WEBGL.GLOBALS.buffers.entitiesTranslations.data[currentEntity.id*6*3+11]=currentEntity.x;
_seba.WEBGL.GLOBALS.buffers.entitiesTranslationsZ.data[currentEntityVertexZIndex+12]=currentEntity.x;
//_seba.WEBGL.GLOBALS.buffers.entitiesTranslations.data[currentEntity.id*6*3+13]=currentEntity.x;
//_seba.WEBGL.GLOBALS.buffers.entitiesTranslations.data[currentEntity.id*6*3+14]=currentEntity.x;
_seba.WEBGL.GLOBALS.buffers.entitiesTranslationsZ.data[currentEntityVertexZIndex+15]=currentEntity.x;
//_seba.WEBGL.GLOBALS.buffers.entitiesTranslations.data[currentEntity.id*6*3+16]=currentEntity.x;
//_seba.WEBGL.GLOBALS.buffers.entitiesTranslations.data[currentEntity.id*6*3+17]=currentEntity.x;
if (currentEntity.isBot){
if (currentEntity.x>currentEntity.xLimit){
currentEntity.x=0-currentEntity.speed;
_seba.WEBGL.GLOBALS.buffers.entitiesTranslationsZ.data[currentEntityVertexZIndex+0]=currentEntity.x;
_seba.WEBGL.GLOBALS.buffers.entitiesTranslationsZ.data[currentEntityVertexZIndex+3]=currentEntity.x;
_seba.WEBGL.GLOBALS.buffers.entitiesTranslationsZ.data[currentEntityVertexZIndex+6]=currentEntity.x;
_seba.WEBGL.GLOBALS.buffers.entitiesTranslationsZ.data[currentEntityVertexZIndex+9]=currentEntity.x;
_seba.WEBGL.GLOBALS.buffers.entitiesTranslationsZ.data[currentEntityVertexZIndex+12]=currentEntity.x;
_seba.WEBGL.GLOBALS.buffers.entitiesTranslationsZ.data[currentEntityVertexZIndex+15]=currentEntity.x;
//--
SEBASTIAN.WEBGL.WORLD.ENTITIES.bootBot(currentEntity.id,currentEntity.id);
SEBASTIAN.WEBGL.WORLD.ENTITIES.syncBuffersData(currentEntity);
}
}
}
//aspect
if (typeof currentEntity.animations!=='undefined'){
//console.log(currentEntity.name,'has animations');
//idle animation
if (currentEntity.isPlayingAnim!==1){
if (typeof currentEntity.animations.idle!=='undefined'){
// we get a random element from the array of available idle animations
var randomIdleAnimId=currentEntity.animations.idle.animations[Math.floor(Math.random()*currentEntity.animations.idle.animations.length)];
//console.log(randomIdleAnimId);
currentEntity.currentAnimation=randomIdleAnimId;
currentEntity.currentAnimationFrameIdx=0;
currentEntity.isPlayingAnim=1;
currentEntity.hasEnteredFrame=0;
currentEntity.saved_textureId=currentEntity.textureId; //salviamo la texture corrente
_seba.WEBGL.WORLD.ENTITIES.syncBuffersData(currentEntity);
}
}else{ // animation execution in progress
if (typeof currentEntity.animations[currentEntity.currentAnimation]!=='undefined'){
if (currentEntity.hasEnteredFrame!==1){
var currentAnim=currentEntity.animations[currentEntity.currentAnimation];
var currentAnimFrameIdx=currentEntity.currentAnimationFrameIdx;
var chance=Math.random(); //0 inclusive 1 exclusive
//console.log(currentAnim.probability_range[0],chance,currentAnim.probability_range[1]);
if ((typeof currentAnim.probability_range==='undefined') || (chance>currentAnim.probability_range[0] && chance<currentAnim.probability_range[1])){
currentEntity.textureId=currentAnim.frames[currentAnimFrameIdx].textureId;
_seba.WEBGL.WORLD.ENTITIES.syncBuffersData(currentEntity);
currentEntity.hasEnteredFrame=1;
currentEntity.frameTimer=0;
if (typeof currentAnim.frames[currentAnimFrameIdx].duration_range!=='undefined') {
var frameDurationMin=currentAnim.frames[currentAnimFrameIdx].duration_range[0];
var frameDurationMax=currentAnim.frames[currentAnimFrameIdx].duration_range[1];
currentEntity.frameDisplayDuration=(Math.random()*(frameDurationMax-frameDurationMin))+frameDurationMin;
}else{
currentEntity.frameDisplayDuration=Infinity; //unlimited duration
}
//console.log('dur',currentEntity.frameDisplayDuration,frameDurationMin,frameDurationMax);
}else{
//console.log(currentEntity.currentAnimation,'failed',chance);
currentEntity.isPlayingAnim=0; // the animation has not been launched -> return to idle state
}
}else{ //we are inside the current animation frame
if (currentEntity.frameDisplayDuration!==Infinity){
var currentAnim=currentEntity.animations[currentEntity.currentAnimation];
currentEntity.frameTimer+=0.001*delta;
//console.log('ft',currentEntity.frameTimer);
if (currentEntity.frameTimer>currentEntity.frameDisplayDuration){
currentEntity.currentAnimationFrameIdx++;
if (currentEntity.currentAnimationFrameIdx>=currentAnim.frames.length){
// we have reached the total number of frames for this animation, return to idle
currentEntity.textureId=currentEntity.saved_textureId;
_seba.WEBGL.WORLD.ENTITIES.syncBuffersData(currentEntity);
currentEntity.isPlayingAnim=0;
}else{ // there are still other frames for this animation
currentEntity.hasEnteredFrame=0;
currentEntity.currentAnimationFrameIdx=0; // reset the current frame
}
}
}
}
}
}
}
},
animateGeometry:function(idx,delta){ //proc animateGeometry {green indent_4}
var _seba=SEBASTIAN;
var worldData=SEBASTIAN.GLOBALS.worldData;
var currentEntity=worldData.entities[idx];
var entitiesVertPosZdata=_seba.WEBGL.GLOBALS.buffers.entitiesVertexPositionsZ.data;
var entitiesVertPosdata=_seba.WEBGL.GLOBALS.buffers.entitiesVertexPositions.data;
var currentEntityVertexZIndex=currentEntity.depthId*6*3;
var currentEntityVertexIndex=currentEntity.id*6*3;
//proc geometry animation behavior RUN {yellow indent_5}
if (currentEntity.behaviorId===2){ //breath geometry deform (organic-life-like)
var ms=currentEntity.deformDelta;
entitiesVertPosZdata[currentEntityVertexZIndex+0 ]=entitiesVertPosdata[currentEntityVertexIndex+0]-ms;
entitiesVertPosZdata[currentEntityVertexZIndex+9 ]=entitiesVertPosdata[currentEntityVertexIndex+9]-ms;
entitiesVertPosZdata[currentEntityVertexZIndex+12]=entitiesVertPosdata[currentEntityVertexIndex+12]-ms;
entitiesVertPosZdata[currentEntityVertexZIndex+1 ]=entitiesVertPosdata[currentEntityVertexIndex+1]-ms;
entitiesVertPosZdata[currentEntityVertexZIndex+10]=entitiesVertPosdata[currentEntityVertexIndex+10]-ms;
entitiesVertPosZdata[currentEntityVertexZIndex+13]=entitiesVertPosdata[currentEntityVertexIndex+13]-ms;
currentEntity.deformDelta=currentEntity.counterDelta;
if (!currentEntity.backCounter)
currentEntity.counterDelta+=currentEntity.counterDeltaIncrement*delta;
else
currentEntity.counterDelta-=currentEntity.counterDeltaIncrement*delta;
if (currentEntity.counterDelta<0 && currentEntity.backCounter){
currentEntity.counterDelta=0;
currentEntity.backCounter=0;
}
if (currentEntity.counterDelta>currentEntity.breathDeformLimit){
currentEntity.backCounter=1;
}
}
if (currentEntity.behaviorId===1){ //taraxacum geometry deform (windflow-like)
var ms=currentEntity.deformDelta;
//if(currentEntity.id===500){
// console.log(delta);
//}
entitiesVertPosZdata[currentEntityVertexZIndex+0 ]=entitiesVertPosdata[currentEntityVertexIndex+0]+ms;
entitiesVertPosZdata[currentEntityVertexZIndex+9 ]=entitiesVertPosdata[currentEntityVertexIndex+9]+ms;
entitiesVertPosZdata[currentEntityVertexZIndex+12]=entitiesVertPosdata[currentEntityVertexIndex+12]+ms;
currentEntity.deformDelta=currentEntity.counterDelta;
if (!currentEntity.isIdle){
if (!currentEntity.backCounter)
currentEntity.counterDelta+=currentEntity.counterDeltaIncrement*delta;
else
currentEntity.counterDelta-=currentEntity.counterDeltaIncrement*delta;
if (currentEntity.counterDelta<0 && currentEntity.backCounter){
currentEntity.counterDelta=0;
currentEntity.backCounter=0;
//--
currentEntity.isIdle=1;
currentEntity.idleCounter=0;
var maxIdleWait=0.2;
var minIdleWait=0.01;
currentEntity.idleWait=(Math.random() * (maxIdleWait-minIdleWait)) + minIdleWait;
}
//console.log(delta);
if (currentEntity.counterDelta>0.2){
currentEntity.backCounter=1;
//--
currentEntity.isIdle=1;
currentEntity.idleCounter=0;
var maxIdleWait=0.2;
var minIdleWait=0.01;
currentEntity.idleWait=(Math.random() * (maxIdleWait-minIdleWait)) + minIdleWait;
}
}else{
currentEntity.idleCounter+=0.001*delta;
if (currentEntity.idleCounter>currentEntity.idleWait){
currentEntity.isIdle=0;
currentEntity.idleCounter=0;
}
}
}
if (currentEntity.behaviorId===3){ //water geometry deform (windflow-like)
var ms=currentEntity.deformDelta;
entitiesVertPosZdata[currentEntityVertexZIndex+0 ]=entitiesVertPosdata[currentEntityVertexIndex+0 ]-ms;
entitiesVertPosZdata[currentEntityVertexZIndex+3 ]=entitiesVertPosdata[currentEntityVertexIndex+3 ]-ms;
entitiesVertPosZdata[currentEntityVertexZIndex+9 ]=entitiesVertPosdata[currentEntityVertexIndex+9 ]-ms;
entitiesVertPosZdata[currentEntityVertexZIndex+12]=entitiesVertPosdata[currentEntityVertexIndex+12]+ms;
entitiesVertPosZdata[currentEntityVertexZIndex+15]=entitiesVertPosdata[currentEntityVertexIndex+15]+ms;
entitiesVertPosZdata[currentEntityVertexZIndex+6 ]=entitiesVertPosdata[currentEntityVertexIndex+6 ]+ms;
entitiesVertPosZdata[currentEntityVertexZIndex+2 ]=entitiesVertPosdata[currentEntityVertexIndex+2 ]-ms;
entitiesVertPosZdata[currentEntityVertexZIndex+11]=entitiesVertPosdata[currentEntityVertexIndex+11]-ms;
entitiesVertPosZdata[currentEntityVertexZIndex+14]=entitiesVertPosdata[currentEntityVertexIndex+14]-ms;
entitiesVertPosZdata[currentEntityVertexZIndex+5 ]=entitiesVertPosdata[currentEntityVertexIndex+5 ]+ms;
entitiesVertPosZdata[currentEntityVertexZIndex+8 ]=entitiesVertPosdata[currentEntityVertexIndex+8 ]+ms;
entitiesVertPosZdata[currentEntityVertexZIndex+17]=entitiesVertPosdata[currentEntityVertexIndex+17]+ms;
currentEntity.deformDelta=currentEntity.counterDelta;
if (!currentEntity.isIdle){
if (!currentEntity.backCounter)
currentEntity.counterDelta+=currentEntity.counterDeltaIncrement*delta;
else
currentEntity.counterDelta-=currentEntity.counterDeltaIncrement*delta;
if (currentEntity.counterDelta<0 && currentEntity.backCounter){
currentEntity.counterDelta=0;
currentEntity.backCounter=0;
//--
currentEntity.isIdle=1;
currentEntity.idleCounter=0;
currentEntity.idleWait=0.2;
}
if (currentEntity.counterDelta>0.20){ //deformation limit
currentEntity.backCounter=1;
//--
currentEntity.isIdle=1;
currentEntity.idleCounter=0;
currentEntity.idleWait=0.2;
}
}else{
currentEntity.idleCounter+=0.001*delta;
if (currentEntity.idleCounter>currentEntity.idleWait){
currentEntity.isIdle=0;
currentEntity.idleCounter=0;
}
}
}
//position 2018-04-30 18:55:57
if (currentEntity.behaviorId===4 || currentEntity.isFloatingOnWater===1){ //breath geometry deform (organic-life-like)
//it is not necessary to update this kind of position animation
//for non-visible elements
//so it goes inside the animateGeometry function even if it does not animate the geometry
if (typeof currentEntity.backCounterY==='undefined'){
currentEntity.backCounterY=1;
currentEntity.timerY=0;
}
if (!currentEntity.backCounterY){
currentEntity.y+=currentEntity.counterDeltaYIncrement*delta;
currentEntity.timerY+=currentEntity.counterDeltaYIncrement;
}else{
currentEntity.y-=currentEntity.counterDeltaYIncrement*delta;
currentEntity.timerY+=currentEntity.counterDeltaYIncrement;
}
//console.log(currentEntity.timerY,currentEntity.counterYTotalDistance);
if (currentEntity.timerY>currentEntity.counterYTotalDistance){
currentEntity.timerY=0;
if (!currentEntity.backCounterY)
currentEntity.backCounterY=1;
else
currentEntity.backCounterY=0;
}
SEBASTIAN.WEBGL.WORLD.ENTITIES.syncBuffersData(currentEntity);
}
},
setGeometry:function(idx){ //proc setGeometry {green indent_4}
//var DYNAMIC_ENTITY_GEOMETRY=1;
var _seba=SEBASTIAN;
var gl=SEBASTIAN.GLOBALS.webgl_ctx; //lookup var
var worldData=SEBASTIAN.GLOBALS.worldData;
var currentEntity=worldData.entities[idx];
var currentEntityTexture;
currentEntityTexture=_seba.WEBGL.GLOBALS.textures[currentEntity.textureId];
if (typeof currentEntityTexture==='undefined'){
console.log('undefined texture',currentEntity.textureId);
currentEntityTexture=_seba.WEBGL.GLOBALS.textures['pavement_01'];
}
if (SEBASTIAN.GLOBALS.dynamicEntitiesGeometry){
//define vertext animation params
currentEntity.deformDelta=0;
currentEntity.counterDelta=0;
currentEntity.backCounter=0;
}
//worldData.entities[idx].dynamicVertexTextureCoordBuffer=SEBASTIAN.WEBGL.WORLD.GLOBALS.globalVertexTextureCoordBuffer;
}
},
}
},
};
SEBASTIAN.init(); //LET'S START THE SHOW
Also see: Tab Triggers