Skip to content
This repository
  • 1 commit
  • 8 files changed
  • 0 comments
  • 1 contributor
Jun 14, 2012
Charles J. Cliffe New closure compiler, experimental getters and setters for readabilit…
…y of code for SceneObject, Light, Camera (x, y, z, rotX, rotY, rotZ, sclX, sclY, sclZ, dirX, dirY, dirZ, targetX, targetY, targetZ, rot, pos, scl, dir), PDF example updated for getters/setters
e440aa8
1  Makefile
@@ -70,6 +70,7 @@ addheader = @@cat $(SRC_DIR)/HEADER > $(DIST_DIR)/header.tmp && \
70 70
 compile = java -jar $(TOOLS_DIR)/closure/compiler.jar \
71 71
                     --js $(CUBICVR_DIST) \
72 72
 	                  --compilation_level SIMPLE_OPTIMIZATIONS \
  73
+			  --language_in ECMASCRIPT5 \
73 74
 	                  --js_output_file $(1)
74 75
 
75 76
 # Convert shader file into js string, removing comments, whitespace, empty lines, and attach to window.CubicVR
1,113  dist/CubicVR.js
@@ -3047,6 +3047,17 @@ CubicVR.RegisterModule("Shader",function(base) {
3047 3047
       }
3048 3048
     },
3049 3049
     _appendShaderVars: function(varList,utype,internal_vars) {
  3050
+        var textureFunc = function(cs,context) { 
  3051
+            return function(idx,texture) {
  3052
+               if (texture !== undef) {
  3053
+                   gl.activeTexture(gl.TEXTURE0+idx);
  3054
+                   gl.bindTexture(GLCore.gl.TEXTURE_2D, base.Textures[texture.tex_id]);
  3055
+               }           
  3056
+               context.value = idx;
  3057
+               cs.update(context);
  3058
+            };
  3059
+        };
  3060
+    
3050 3061
       for (var i = 0, iMax = this._shaderVars[utype].length; i < iMax; i++) {
3051 3062
         var sv = this._shaderVars[utype][i];
3052 3063
         var svloc = sv.location;
@@ -3086,23 +3097,22 @@ CubicVR.RegisterModule("Shader",function(base) {
3086 3097
         if (svtype=="sampler2D" && binding) {
3087 3098
             var cs = this;
3088 3099
             var gl = GLCore.gl;
3089  
-            binding.set = function(cs,context) { return function(idx,texture) {
3090  
-               if (texture !== undef) {
3091  
-                   gl.activeTexture(gl.TEXTURE0+idx);
3092  
-                   gl.bindTexture(GLCore.gl.TEXTURE_2D, base.Textures[texture.tex_id]);
3093  
-               }           
3094  
-               context.value = idx;
3095  
-               cs.update(context);
3096  
-             };
3097  
-            }(this,binding);
  3100
+            binding.set = textureFunc(this,binding);
3098 3101
         }
3099 3102
       }
3100 3103
     },
3101 3104
     
3102 3105
     _bindSelf: function(uniform_id) {  
3103 3106
       var t,k,p,v,bindval;
3104  
-      
  3107
+
3105 3108
       if (this._shader.uniforms[uniform_id]===null) return;
  3109
+
  3110
+      var bindSetFunc = function(cs,context) { 
  3111
+        return function(value) {
  3112
+           context.value = value;
  3113
+           cs.update(context);
  3114
+        };
  3115
+      };
3106 3116
       
3107 3117
       if (uniform_id.indexOf(".")!==-1) {
3108 3118
         if (uniform_id.indexOf("[")!==-1) {
@@ -3158,11 +3168,7 @@ CubicVR.RegisterModule("Shader",function(base) {
3158 3168
       }
3159 3169
       
3160 3170
       if (bindval) {
3161  
-        bindval.set = function(cs,context) { return function(value) {
3162  
-           context.value = value;
3163  
-           cs.update(context);
3164  
-         };
3165  
-        }(this,bindval);
  3171
+        bindval.set = bindSetFunc(this,bindval);
3166 3172
       }
3167 3173
       
3168 3174
       return bindval;
@@ -4514,6 +4520,219 @@ CubicVR.RegisterModule("Texture", function (base) {
4514 4520
     return extend;
4515 4521
 });
4516 4522
 
  4523
+
  4524
+CubicVR.RegisterModule("DrawBufferTexture", function (base) {
  4525
+
  4526
+    var GLCore = base.GLCore;
  4527
+    var enums = base.enums;
  4528
+    var undef = base.undef;
  4529
+    var log = base.log;
  4530
+
  4531
+    // Drawing Enums
  4532
+    enums.draw = {
  4533
+        brush: {
  4534
+            SINE: 0,
  4535
+            SQUARE: 1
  4536
+        },
  4537
+        op: {
  4538
+            ADD: 0,
  4539
+            REPLACE: 1,
  4540
+            SUBTRACT: 2,
  4541
+            MULTIPLY: 3
  4542
+        }
  4543
+    };
  4544
+    
  4545
+    var DrawBufferBrush = function(opt) {
  4546
+        opt = opt || {};
  4547
+        
  4548
+        this.operation = base.parseEnum(enums.draw.op,opt.operation||opt.op)||enums.draw.op.REPLACE;
  4549
+        this.brushType = base.parseEnum(enums.draw.brush,opt.brushType)||enums.draw.brush.SINE;
  4550
+        this.brushSize = opt.size||5;
  4551
+        this.color = opt.color||[255,255,255,255];
  4552
+    };
  4553
+    
  4554
+    DrawBufferBrush.prototype = {
  4555
+        setOperation: function(brushOperation) {
  4556
+            this.operation = base.parseEnum(enums.draw.op,brushOperation);
  4557
+        },
  4558
+        getOperation: function() {
  4559
+            return this.operation;
  4560
+        },
  4561
+        setBrushType: function(brushType) {
  4562
+            this.brushType = base.parseEnum(enums.draw.brush,brushType)||enums.draw.brush.SINE;
  4563
+        },
  4564
+        getBrushType: function() {
  4565
+            return this.brushType;
  4566
+        },
  4567
+        setSize: function(brushSize) {
  4568
+            this.brushSize = brushSize;
  4569
+        },
  4570
+        getSize: function() {
  4571
+            return this.brushSize;
  4572
+        },
  4573
+        setColor: function(color) {
  4574
+            this.color = color;
  4575
+        },
  4576
+        getColor: function() {
  4577
+            return this.color.slice(0);
  4578
+        }
  4579
+    };
  4580
+    
  4581
+    var DrawBufferTexture = base.extendClassGeneral(base.Texture, function() {
  4582
+        var opt = arguments[0]||{};
  4583
+
  4584
+        // temporary
  4585
+        var img_path = opt.image;
  4586
+        var filter_type = opt.filter;
  4587
+        var deferred_bin = opt.deferred_bin;
  4588
+        var binId = opt.binId;
  4589
+        var ready_func = opt.readyFunc;
  4590
+        // end temp..
  4591
+
  4592
+        base.Texture.apply(this,[img_path, filter_type, deferred_bin, binId, ready_func]);
  4593
+
  4594
+        this.width = opt.width||0;
  4595
+        this.height = opt.height||0;
  4596
+        this.imageBuffer = null;
  4597
+        this.imageBufferData = null;
  4598
+        this.brush = opt.brush||new DrawBufferBrush();
  4599
+        // this.imageBufferFloatData = null;
  4600
+        this.drawBuffer = [];
  4601
+
  4602
+        if (this.width && this.height) {
  4603
+            this.setupImageBuffer(this.width,this.height);
  4604
+        }
  4605
+        
  4606
+
  4607
+    },{ // DrawBufferTexture functions
  4608
+        needsFlush: function() {
  4609
+            return this.drawBuffer.length!==0;
  4610
+        },
  4611
+        getWidth: function() {
  4612
+            return this.width;
  4613
+        },
  4614
+        getHeight: function() {
  4615
+            return this.height;
  4616
+        },
  4617
+        setupImageBuffer: function () {
  4618
+            this.imageBufferData = new ArrayBuffer(this.width*this.height*4);
  4619
+            this.imageBuffer = new Uint8Array(this.imageBufferData);
  4620
+            this.update();
  4621
+            // this.imageBufferFloatData = new Float32Array(this.imageBufferData); 
  4622
+        },
  4623
+        setBrush: function(brush) {
  4624
+            this.brush = brush;
  4625
+        },
  4626
+        getBrush: function() {
  4627
+            return this.brush;
  4628
+        },
  4629
+        draw: function(x,y,brush_in) {
  4630
+            var brush = this.brush||brush_in;
  4631
+            var op = brush.getOperation();
  4632
+            var size = brush.getSize();
  4633
+            var btype = brush.getBrushType();
  4634
+            var color = brush.getColor();
  4635
+            
  4636
+            this.drawBuffer.push([x,y,op,size,btype,color]);            
  4637
+        },
  4638
+        flush: function() {
  4639
+          if (!this.drawBuffer.length) {
  4640
+              return false;
  4641
+          }
  4642
+          while (this.drawBuffer.length) {
  4643
+              var ev = this.drawBuffer.pop();
  4644
+              
  4645
+              this.drawFunc(ev[0],ev[1],ev[2],ev[3],ev[4],ev[5]);
  4646
+          }
  4647
+          return true;
  4648
+        },
  4649
+        drawFunc: function(x,y,op,size,btype,color) {
  4650
+            var imageData = this.imageBuffer;
  4651
+            var width = this.width;
  4652
+            var height = this.height;
  4653
+            
  4654
+            for (var i = parseInt(Math.floor(x),10) - size; i < parseInt(Math.ceil(x),10) + size; i++) {
  4655
+                var dx = i-x, dy;
  4656
+                for (var j = parseInt(Math.floor(y),10) - size; j < parseInt(Math.ceil(y),10) + size; j++) {
  4657
+                    if (i <= 0 || i >= width || j <= 0 || j >= height) continue;
  4658
+                    dy = j - y;
  4659
+                    
  4660
+                    var val;
  4661
+                    
  4662
+                    if (btype === 0) { // SINE
  4663
+                        val = ((1.0 - Math.sqrt(dx * dx + dy * dy) / (size)) / 2.0);
  4664
+                    }
  4665
+
  4666
+                    var idx = (j * width + i)*4;
  4667
+
  4668
+                    // todo: implement other than just replace..
  4669
+                    if (op === 0) { // ADD 
  4670
+                        if (val < 0) val = 0;
  4671
+                    } else if (op === 1) { // REPLACE
  4672
+                        if (val < 0) val = 0;
  4673
+                    } else if (op === 2) { // SUBTRACT
  4674
+                        val = -val;
  4675
+                        if (val > 0) val = 0;
  4676
+                    } 
  4677
+                    // else if (op === 3) { // MULTIPLY                        
  4678
+                    // }
  4679
+
  4680
+                    var r = Math.floor(imageData[idx]*(1.0-val)+color[0]*val);
  4681
+                    var g = Math.floor(imageData[idx+1]*(1.0-val)+color[1]*val);
  4682
+                    var b = Math.floor(imageData[idx+2]*(1.0-val)+color[2]*val);
  4683
+                    var a = Math.floor(imageData[idx+3]*(1.0-val)+color[3]*val);
  4684
+
  4685
+                    if (r > 255) { r = 255; } else if (r < 0) { r = 0; }
  4686
+                    if (g > 255) { g = 255; } else if (g < 0) { g = 0; }
  4687
+                    if (b > 255) { b = 255; } else if (b < 0) { b = 0; }
  4688
+                    if (a > 255) { a = 255; } else if (a < 0) { a = 0; }
  4689
+
  4690
+                    imageData[idx] = r;
  4691
+                    imageData[idx+1] = g;
  4692
+                    imageData[idx+2] = b;
  4693
+                    imageData[idx+3] = a;
  4694
+                }
  4695
+            }
  4696
+        },
  4697
+        // clear: function() {
  4698
+        //   
  4699
+        //     function draw_rgba_clear(imageData, width, height, color, x, y, sz, h) {
  4700
+        //         for (var i = x - w; i < x + w; i++) {
  4701
+        //             var dx = i - x, dy;
  4702
+        // 
  4703
+        //             for (var j = y - h; j < y + h; j++) {
  4704
+        //                 var idx = (j * width + i) * 4;
  4705
+        //                 hfBuffer[idx] = 0;
  4706
+        //                 hfBuffer[idx+1] = 0;
  4707
+        //                 hfBuffer[idx+2] = 0;
  4708
+        //                 hfBuffer[idx+3] = 0;
  4709
+        //             }
  4710
+        //         }
  4711
+        //     }
  4712
+        //   
  4713
+        // },
  4714
+        update: function() {
  4715
+            var gl = GLCore.gl;
  4716
+
  4717
+            this.flush();
  4718
+            
  4719
+            // gl.disable(gl.BLEND);
  4720
+            // gl.blendFunc(gl.ONE,gl.ONE);
  4721
+            gl.bindTexture(gl.TEXTURE_2D, base.Textures[this.tex_id]);
  4722
+            // gl.pixelStorei(gl.UNPACK_PREMULTIPLY_ALPHA_WEBGL, false);            
  4723
+            gl.texImage2D(gl.TEXTURE_2D, 0, gl.RGBA, this.width, this.height, 0, gl.RGBA, gl.UNSIGNED_BYTE, this.imageBuffer);
  4724
+        }        
  4725
+    });
  4726
+
  4727
+
  4728
+    var extend = {
  4729
+        DrawBufferTexture: DrawBufferTexture,
  4730
+        DrawBufferBrush: DrawBufferBrush
  4731
+    };
  4732
+
  4733
+    return extend;
  4734
+});
  4735
+
4517 4736
 CubicVR.RegisterModule("Material", function(base) {
4518 4737
   var undef = base.undef;
4519 4738
   var GLCore = base.GLCore;
@@ -4968,16 +5187,9 @@ CubicVR.RegisterModule("Material", function(base) {
4968 5187
         sh.use();
4969 5188
 
4970 5189
         if (sh.materialTexOffset != -1) gl.uniform2fv(sh.materialTexOffset, [0,0]);
4971  
-
4972  
-        if (this.customShader) {
4973  
-          this.customShader._doUpdate({material:this});
4974  
-        }        
4975 5190
       } else {
4976 5191
         success = (sh !== failSafeShader);
4977 5192
         sh.use();
4978  
-        if (this.customShader && !noCustomDepthPack) {
4979  
-          this.customShader._doUpdate({material:this});
4980  
-        }
4981 5193
       }
4982 5194
 
4983 5195
 
@@ -5050,6 +5262,12 @@ CubicVR.RegisterModule("Material", function(base) {
5050 5262
 
5051 5263
       if (sh.materialTexOffset) gl.uniform2fv(sh.materialTexOffset, this.uvOffset);
5052 5264
       
  5265
+      if (this.customShader) {
  5266
+          if (light_type !== enums.light.type.DEPTH_PACK || (light_type === enums.light.type.DEPTH_PACK && !noCustomDepthPack)) {
  5267
+              this.customShader._doUpdate({material:this,textureIndex:m});
  5268
+          }
  5269
+      }
  5270
+
5053 5271
       return success;
5054 5272
     }
5055 5273
   };
@@ -8003,6 +8221,78 @@ CubicVR.RegisterModule("Light", function (base) {
8003 8221
     }
8004 8222
 
8005 8223
     Light.prototype = {
  8224
+        get x(){
  8225
+            return this.position[0];
  8226
+        },
  8227
+        set x(val){
  8228
+            this.position[0] = val;
  8229
+        },
  8230
+        get y(){
  8231
+            return this.position[1];
  8232
+        },
  8233
+        set y(val){
  8234
+            this.position[1] = val;
  8235
+        },
  8236
+        get z(){
  8237
+            return this.position[2];
  8238
+        },
  8239
+        set z(val){
  8240
+            this.position[2] = val;
  8241
+        },
  8242
+        get rotX(){
  8243
+            return this.rotation[0];
  8244
+        },
  8245
+        set rotX(val){
  8246
+            this.rotation[0] = val;
  8247
+        },
  8248
+        get rotY(){
  8249
+            return this.rotation[1];
  8250
+        },
  8251
+        set rotY(val){
  8252
+            this.rotation[1] = val;
  8253
+        },
  8254
+        get rotZ(){
  8255
+            return this.rotation[2];
  8256
+        },
  8257
+        set rotZ(val){
  8258
+            this.rotation[2] = val;
  8259
+        },
  8260
+        get dirX(){
  8261
+            return this.direction[0];
  8262
+        },
  8263
+        set dirX(val){
  8264
+            this.direction[0] = val;
  8265
+        },
  8266
+        get dirY(){
  8267
+            return this.direction[1];
  8268
+        },
  8269
+        set dirY(val){
  8270
+            this.direction[1] = val;
  8271
+        },
  8272
+        get dirZ(){
  8273
+            return this.direction[2];
  8274
+        },
  8275
+        set dirZ(val){
  8276
+            this.direction[2] = val;
  8277
+        },
  8278
+        get pos(){
  8279
+            return this.position.slice(0);
  8280
+        },        
  8281
+        set pos(val){
  8282
+            this.position = val.slice(0);
  8283
+        },
  8284
+        get rot(){
  8285
+            return this.rotation.slice(0);
  8286
+        },        
  8287
+        set rot(val){
  8288
+            this.rotation = val.slice(0);
  8289
+        },
  8290
+        get dir(){
  8291
+            return this.direction.slice(0);
  8292
+        },        
  8293
+        set dir(val){
  8294
+            this.direction = vec3.normalize(val.slice(0));
  8295
+        },
8006 8296
         setType: function (light_type) {
8007 8297
             if (light_type === enums.light.type.AREA && !base.features.lightShadows) {
8008 8298
                 this.dummyCam = new base.Camera();
@@ -8449,6 +8739,73 @@ CubicVR.RegisterModule("Camera", function (base) {
8449 8739
     }
8450 8740
 
8451 8741
     Camera.prototype = {
  8742
+        get x(){
  8743
+            return this.position[0];
  8744
+        },
  8745
+        set x(val){
  8746
+            this.position[0] = val;
  8747
+        },
  8748
+        get y(){
  8749
+            return this.position[1];
  8750
+        },
  8751
+        set y(val){
  8752
+            this.position[1] = val;
  8753
+        },
  8754
+        get z(){
  8755
+            return this.position[2];
  8756
+        },
  8757
+        set z(val){
  8758
+            this.position[2] = val;
  8759
+        },
  8760
+        get rotX(){
  8761
+            return this.rotation[0];
  8762
+        },
  8763
+        set rotX(val){
  8764
+            this.rotation[0] = val;
  8765
+        },
  8766
+        get rotY(){
  8767
+            return this.rotation[1];
  8768
+        },
  8769
+        set rotY(val){
  8770
+            this.rotation[1] = val;
  8771
+        },
  8772
+        get rotZ(){
  8773
+            return this.rotation[2];
  8774
+        },
  8775
+        set rotZ(val){
  8776
+            this.rotation[2] = val;
  8777
+        },
  8778
+        get targetX(){
  8779
+            return this.target[0];
  8780
+        },
  8781
+        set targetX(val){
  8782
+            this.target[0] = val;
  8783
+        },
  8784
+        get targetY(){
  8785
+            return this.target[1];
  8786
+        },
  8787
+        set targetY(val){
  8788
+            this.target[1] = val;
  8789
+        },
  8790
+        get targetZ(){
  8791
+            return this.target[2];
  8792
+        },
  8793
+        set targetZ(val){
  8794
+            this.target[2] = val;
  8795
+        },
  8796
+        get pos(){
  8797
+            return this.position.slice(0);
  8798
+        },        
  8799
+        set pos(val){
  8800
+            this.position = val.slice(0);
  8801
+        },
  8802
+        get rot(){
  8803
+            return this.rotation.slice(0);
  8804
+        },        
  8805
+        set rot(val){
  8806
+            this.rotation = val.slice(0);
  8807
+        },
  8808
+        
8452 8809
         trackTarget: function(targetPos, speed, safeDist) {
8453 8810
           this.position = base.vec3.trackTarget(this.position,targetPos,speed,safeDist);
8454 8811
         },
@@ -10017,7 +10374,79 @@ CubicVR.RegisterModule("Scene", function (base) {
10017 10374
         this.independentMotion = false;
10018 10375
     }
10019 10376
 
10020  
-    SceneObject.prototype = {
  10377
+    SceneObject.prototype = {   // getters and setters for x, y, z, rotX, rotY, rotZ, sclX, sclY, sclZ, rot, pos, scale
  10378
+        get x(){
  10379
+            return this.position[0];
  10380
+        },
  10381
+        set x(val){
  10382
+            this.position[0] = val;
  10383
+        },
  10384
+        get y(){
  10385
+            return this.position[1];
  10386
+        },
  10387
+        set y(val){
  10388
+            this.position[1] = val;
  10389
+        },
  10390
+        get z(){
  10391
+            return this.position[2];
  10392
+        },
  10393
+        set z(val){
  10394
+            this.position[2] = val;
  10395
+        },
  10396
+        get rotX(){
  10397
+            return this.rotation[0];
  10398
+        },
  10399
+        set rotX(val){
  10400
+            this.rotation[0] = val;
  10401
+        },
  10402
+        get rotY(){
  10403
+            return this.rotation[1];
  10404
+        },
  10405
+        set rotY(val){
  10406
+            this.rotation[1] = val;
  10407
+        },
  10408
+        get rotZ(){
  10409
+            return this.rotation[2];
  10410
+        },
  10411
+        set rotZ(val){
  10412
+            this.rotation[2] = val;
  10413
+        },
  10414
+        get pos(){
  10415
+            return this.position.slice(0);
  10416
+        },        
  10417
+        set pos(val){
  10418
+            this.position = val.slice(0);
  10419
+        },
  10420
+        get rot(){
  10421
+            return this.rotation.slice(0);
  10422
+        },        
  10423
+        set rot(val){
  10424
+            this.rotation = val.slice(0);
  10425
+        },
  10426
+        get sclX(){
  10427
+            return this.scale[0];
  10428
+        },
  10429
+        set sclX(val){
  10430
+            this.scale[0] = val;
  10431
+        },
  10432
+        get sclY(){
  10433
+            return this.scale[1];
  10434
+        },
  10435
+        set sclY(val){
  10436
+            this.scale[1] = val;
  10437
+        },
  10438
+        get sclZ(){
  10439
+            return this.scale[2];
  10440
+        },
  10441
+        set sclZ(val){
  10442
+            this.scale[2] = val;
  10443
+        },
  10444
+        get scl(){
  10445
+            return this.scale.slice(0);
  10446
+        },        
  10447
+        set scl(val){
  10448
+            this.scale = val.slice(0);
  10449
+        },        
10021 10450
         clone: function() {
10022 10451
             var i,iMax;
10023 10452
             var newName = this.name?(this.name+"_"+this.duplicateCount):null;
@@ -15223,7 +15652,6 @@ CubicVR.RegisterModule("Particles",function(base) {
15223 15652
 
15224 15653
 CubicVR.RegisterModule("HeightField", function(base) {
15225 15654
     
15226  
-    // heightfield is a fork and simplification of Landscape, hopefully for use in larger dynamic structures :)
15227 15655
     var undef = base.undef;
15228 15656
     var enums = base.enums;
15229 15657
     var GLCore = base.GLCore;
@@ -15233,177 +15661,405 @@ CubicVR.RegisterModule("HeightField", function(base) {
15233 15661
     var M_TWO_PI = 2.0 * Math.PI;
15234 15662
     var M_HALF_PI = Math.PI / 2.0;
15235 15663
 
15236  
-    var heightfield_enums = {
  15664
+    // Drawing Enums
  15665
+    enums.heightfield = {
  15666
+        brush: {
  15667
+            SINE: 0,
  15668
+            SQUARE: 1
  15669
+        },
  15670
+        op: {
  15671
+            ADD: 0,
  15672
+            REPLACE: 1,
  15673
+            SUBTRACT: 2
  15674
+        }
  15675
+    };
  15676
+    
  15677
+    // Landscape has been forked into Landscape/HeightField/HeightFieldBrush/HeightFieldMesh
  15678
+    
  15679
+    var HeightFieldBrush = function(opt) {
  15680
+        opt = opt || {};
15237 15681
         
  15682
+        this.operation = base.parseEnum(enums.draw.op,opt.operation||opt.op)||enums.draw.op.REPLACE;
  15683
+        this.brushType = base.parseEnum(enums.draw.brush,opt.brushType)||enums.draw.brush.SINE;
  15684
+        this.brushSize = opt.size||5;
  15685
+        this.strength = opt.strength||1;
  15686
+    };
  15687
+    
  15688
+    HeightFieldBrush.prototype = {
  15689
+        setOperation: function(brushOperation) {
  15690
+            this.operation = base.parseEnum(enums.draw.op,brushOperation);
  15691
+        },
  15692
+        getOperation: function() {
  15693
+            return this.operation;
  15694
+        },
  15695
+        setBrushType: function(brushType) {
  15696
+            this.brushType = base.parseEnum(enums.draw.brush,brushType)||enums.draw.brush.SINE;
  15697
+        },
  15698
+        getBrushType: function() {
  15699
+            return this.brushType;
  15700
+        },
  15701
+        setSize: function(brushSize) {
  15702
+            this.brushSize = brushSize;
  15703
+        },
  15704
+        getSize: function() {
  15705
+            return this.brushSize;
  15706
+        },
  15707
+        setStrength: function(strength) {
  15708
+            this.strength = strength;
  15709
+        },
  15710
+        getStrength: function() {
  15711
+            return this.strength;
  15712
+        }
15238 15713
     };
15239 15714
 
15240  
-    enums.heightfield = heightfield_enums;
15241  
-
15242  
-    function HeightField(opt) {
  15715
+    var HeightField = function(opt) {
15243 15716
         opt = opt||{};
15244  
-        opt = base.get(opt);
15245 15717
         
15246  
-        this.size = opt.size;
15247  
-        this.material = opt.material||(new base.Material());
15248  
-        this.divX = opt.divX|0;
15249  
-        this.divZ = opt.divZ|0;
  15718
+        this.divX = opt.divX||null;
  15719
+        this.divZ = opt.divZ||null;
  15720
+        this.size = opt.size||null;
15250 15721
         
15251  
-        this.obj = null;
15252  
-
15253  
-        if (this.divX > this.divZ) {
15254  
-            this.sizeX = this.size;
15255  
-            this.sizeZ = (this.size / this.divX) * this.divZ;
15256  
-        } else if (this.divZ > this.divX) {
15257  
-            this.sizeX = (this.size / this.divZ) * this.divX;
15258  
-            this.sizeZ = this.size;
15259  
-        } else {
15260  
-            this.sizeX = this.size;
15261  
-            this.sizeZ = this.size;
15262  
-        }
15263  
-    }
  15722
+        this.hfBuffer = null;
  15723
+        this.hfUInt8Buffer = null;
  15724
+        this.hfFloatBuffer = null;
  15725
+        this.cellSize = null;
  15726
+        this.sizeX = null;
  15727
+        this.sizeZ = null;
  15728
+        this.cellSize = null;
15264 15729
 
  15730
+        if (this.divX && this.divZ && this.size) {
  15731
+            this.initBuffer(this.divX,this.divZ,this.size);
  15732
+        }
  15733
+        
  15734
+    };
  15735
+    
15265 15736
     HeightField.prototype = {
15266  
-        getMesh: function () {
15267  
-            if (this.obj === null) {
15268  
-                this.obj = this.genMesh();
  15737
+        initBuffer: function(divX,divZ,size) {
  15738
+            this.hfBuffer = new ArrayBuffer(divX*divZ*4);
  15739
+            this.hfUInt8Buffer = new Uint8Array(this.hfBuffer);
  15740
+            this.hfFloatBuffer = new Float32Array(this.hfBuffer);
  15741
+
  15742
+            this.divX = divX||null;
  15743
+            this.divZ = divZ||null;
  15744
+            this.size = size||null;
  15745
+            
  15746
+            if (this.divX > this.divZ) {
  15747
+                this.sizeX = size;
  15748
+                this.sizeZ = (size / this.divX) * this.divZ;
  15749
+            } else if (this.divZ > this.divX) {
  15750
+                this.sizeX = (size / this.divZ) * this.divX;
  15751
+                this.sizeZ = size;
  15752
+            } else {
  15753
+                this.sizeX = size;
  15754
+                this.sizeZ = size;
15269 15755
             }
15270  
-            return this.obj;
  15756
+            
  15757
+            
  15758
+            this.drawBuffer = [];
  15759
+            this.cellSize = this.sizeX/this.divX;
15271 15760
         },
15272  
-
15273  
-        setIndexedHeight: function (ipos, jpos, val) {
15274  
-            obj.points[(ipos) + (jpos * this.divX)][1] = val;
  15761
+        setBrush: function(brush) {
  15762
+            this.brush = brush;
15275 15763
         },
15276  
-
15277  
-        genMesh: function() {
15278  
-            var obj = new base.Mesh({dynamic:true,buildWireframe:true});
  15764
+        getBrush: function() {
  15765
+            return this.brush;
  15766
+        },
  15767
+        draw: function(x,z,brush_in) {
  15768
+            var brush = this.brush||brush_in;
  15769
+            var op = brush.getOperation();
  15770
+            var size = brush.getSize();
  15771
+            var btype = brush.getBrushType();
  15772
+            var strength = brush.getStrength();
15279 15773
             
15280  
-            var i, j;
15281  
-
15282  
-            for (j = -(this.sizeZ / 2.0); j < (this.sizeZ / 2.0); j += (this.sizeZ / this.divZ)) {
15283  
-                for (i = -(this.sizeX / 2.0); i < (this.sizeX / 2.0); i += (this.sizeX / this.divX)) {
15284  
-                    obj.addPoint([i + ((this.sizeX / (this.divX)) / 2.0), 0, j + ((this.sizeZ / (this.divZ)) / 2.0)]);
15285  
-                }
15286  
-            }
  15774
+            this.drawBuffer.push([x,z,op,size,btype,strength]); 
  15775
+        },
  15776
+        flush: function() {
  15777
+          if (!this.drawBuffer.length) {
  15778
+              return false;
  15779
+          }
  15780
+          while (this.drawBuffer.length) {
  15781
+              var ev = this.drawBuffer.pop();
  15782
+              this.drawFunc(ev[0],ev[1],ev[2],ev[3],ev[4],ev[5]);
  15783
+          }
  15784
+          return true;
  15785
+        },        
  15786
+        needsFlush: function() {
  15787
+            return this.drawBuffer.length!==0;
  15788
+        },
  15789
+        drawFunc: function(x,z,op,size,btype,strength) {
  15790
+            var hfBuffer = this.hfFloatBuffer;
  15791
+            var hfWidth = this.divX;
  15792
+            var hfDepth = this.divZ;
  15793
+            
  15794
+            var sz = size/this.cellSize;
  15795
+            var ofs_w = (this.sizeX / 2.0) - ((this.sizeX / (this.divX)) / 2.0);
  15796
+            var ofs_h = (this.sizeZ / 2.0) - ((this.sizeZ / (this.divZ)) / 2.0);
  15797
+            
  15798
+            x += ofs_w;
  15799
+            z += ofs_h;
15287 15800
 
15288  
-            var k, l;
  15801
+            x /= this.cellSize;
  15802
+            z /= this.cellSize;
15289 15803
 
15290  
-            obj.setFaceMaterial(this.material);
  15804
+            for (var i = parseInt(Math.floor(x - sz),10), iMax = parseInt(Math.ceil(x + sz),10); i < iMax; i++) {
  15805
+                var dx = i - x;
15291 15806
 
15292  
-            for (l = 0; l < this.divZ - 1; l++) {
15293  
-                for (k = 0; k < this.divX - 1; k++) {
15294  
-                    obj.addFace([(k) + ((l + 1) * this.divX), (k + 1) + ((l) * this.divX), (k) + ((l) * this.divX)]);
15295  
-                    obj.addFace([(k) + ((l + 1) * this.divX), (k + 1) + ((l + 1) * this.divX), (k + 1) + ((l) * this.divX)]);
  15807
+                for (var j = parseInt(Math.floor(z - sz),10), jMax = parseInt(Math.ceil(z + sz),10); j < jMax; j++) {
  15808
+                    if (i <= 0 || i >= hfWidth || j <= 0 || j >= hfDepth) continue;
  15809
+                    var dz = j - z;
  15810
+                    // todo: implement ops..
  15811
+                    var val = strength * ((1.0 - Math.sqrt(dx * dx + dz * dz) / (sz)) / 2.0);
  15812
+                    
  15813
+                    if (val < 0 && strength >= 0) val = 0;
  15814
+                    if (val > 0 && strength <= 0) val = 0;
  15815
+                    hfBuffer[j * hfWidth + i] += val;
15296 15816
                 }
15297 15817
             }
15298  
-            
15299  
-            return obj;
15300 15818
         },
15301  
-        
15302  
-        mapGen: function (opt) {
  15819
+        getUint8Buffer: function() {
  15820
+            return this.hfUInt8Buffer;
  15821
+        },
  15822
+        getFloat32Buffer: function() {
  15823
+            return this.hfFloatBuffer;
  15824
+        },
  15825
+        getDivX: function() {
  15826
+            return this.divX;
  15827
+        },
  15828
+        getDivZ: function() {
  15829
+            return this.divZ;
  15830
+        },
  15831
+        getSizeX: function() {
  15832
+            return this.sizeX;  
  15833
+        },        
  15834
+        getSizeZ: function() {
  15835
+            return this.sizeZ;  
  15836
+        },        
  15837
+        getCellSize: function() {
  15838
+            return this.cellSize;
  15839
+        },
  15840
+        getSize: function() {
  15841
+            return this.size;
  15842
+        },
  15843
+        setRect: function (opt) {
  15844
+            opt = opt||{};
  15845
+             var setvalue = opt.value||0;
  15846
+             var w_func = opt.src||opt.func||null;
  15847
+             var ipos = opt.startX||0;
  15848
+             var jpos = opt.startZ||0;
  15849
+             var ilen = opt.walkX;
  15850
+             var jlen = opt.walkZ;
  15851
+             var hfBuffer = this.hfFloatBuffer;
  15852
+
  15853
+             var pt,i,imax;
  15854
+
  15855
+             var ofs_w = (this.sizeX / 2.0) - ((this.sizeX / (this.divX)) / 2.0);
  15856
+             var ofs_h = (this.sizeZ / 2.0) - ((this.sizeZ / (this.divZ)) / 2.0);
  15857
+
  15858
+             if (ipos !== undef && jpos !== undef && ilen !== undef && jlen !== undef) {
  15859
+                 if (ipos >= this.divX) return;
  15860
+                 if (jpos >= this.divZ) return;
  15861
+                 if (ipos + ilen >= this.divX) ilen = this.divX - 1 - ipos;
  15862
+                 if (jpos + jlen >= this.divZ) jlen = this.divZ - 1 - jpos;
  15863
+                 if (ilen <= 0 || jlen <= 0) return;
  15864
+
  15865
+                 for (i = ipos, imax = ipos + ilen; i < imax; i++) {
  15866
+                     for (var j = jpos, jmax = jpos + jlen; j < jmax; j++) {
  15867
+                         var t = (i) + (j * this.divX);
  15868
+                         
  15869
+                         if (w_func===null) {
  15870
+                             hfBuffer[t] = setvalue;
  15871
+                         } else {
  15872
+                             hfBuffer[t] = w_func(this.cellSize*i-ofs_w, this.cellSize*j-ofs_h, t);
  15873
+                         }
  15874
+                     }
  15875
+                 }
  15876
+             } else {
  15877
+                 for (i = 0, imax = this.hfFloatBuffer.length; i < imax; i++) {
  15878
+                     if (w_func===null) {
  15879
+                         hfBuffer[i] = setvalue;
  15880
+                     } else {
  15881
+                         var val = w_func((i%this.divX)*this.cellSize-ofs_w, (Math.floor(i/this.divX))*this.cellSize-ofs_h, i);
  15882
+                         hfBuffer[i] = val;
  15883
+                     }
  15884
+                 }
  15885
+             }
  15886
+         },
15303 15887
 
15304  
-            var w_func = opt.src||function() { return 0; }; 
15305  
-            var ipos = opt.startX||0;
15306  
-            var jpos = opt.startZ||0;
15307  
-            var ilen = opt.walkX;
15308  
-            var jlen = opt.walkZ;
15309  
-        
15310  
-            var pt,i,imax;
  15888
+         getIndicesAt: function (x, z) {
  15889
+             // pretend we have faces and construct the triangle that forms at x,z
  15890
+             if (typeof (x) === 'object') {
  15891
+                 return this.getFaceAt(x[0], x[2]);
  15892
+             }
15311 15893
 
15312  
-            if (ipos !== undef && jpos !== undef && ilen !== undef && jlen !== undef) {
15313  
-                if (ipos >= this.divX) return;
15314  
-                if (jpos >= this.divZ) return;
15315  
-                if (ipos + ilen >= this.divX) ilen = this.divX - 1 - ipos;
15316  
-                if (jpos + jlen >= this.divZ) jlen = this.divZ - 1 - jpos;
15317  
-                if (ilen <= 0 || jlen <= 0) return;
  15894
+             var ofs_w = (this.sizeX / 2.0) - ((this.sizeX / (this.divX)) / 2.0);
  15895
+             var ofs_h = (this.sizeZ / 2.0) - ((this.sizeZ / (this.divZ)) / 2.0);
15318 15896
 
15319  
-                for (i = ipos, imax = ipos + ilen; i < imax; i++) {
15320  
-                    for (var j = jpos, jmax = jpos + jlen; j < jmax; j++) {
15321  
-                        var t = (i) + (j * this.divX);
15322  
-                        pt = this.obj.points[t];
  15897
+             var i = parseInt(Math.floor(((x + ofs_w) / this.sizeX) * (this.divX)), 10);
  15898
+             var j = parseInt(Math.floor(((z + ofs_h) / this.sizeZ) * (this.divZ)), 10);
  15899
+             
  15900
+             if (i < 0) {
  15901
+                 return -1;
  15902
+             }
  15903
+             if (i >= this.divX - 1) {
  15904
+                 return -1;
  15905
+             }
  15906
+             if (j < 0) {
  15907
+                 return -1;
  15908
+             }
  15909
+             if (j >= this.divZ - 1) {
  15910
+                 return -1;
  15911
+             }
  15912
+             
  15913
+             // todo: this seems a tad wasteful..
  15914
+             var slope = Math.abs(z-ofs_h - (i*this.cellSize-ofs_h)) / Math.abs(x-ofs_w - (j*this.cellSize-ofs_h));
15323 15915
 
15324  
-                        pt[1] = w_func(pt[0], pt[2], t);
15325  
-                    }
15326  
-                }
15327  
-            } else {
15328  
-                for (i = 0, imax = this.obj.points.length; i < imax; i++) {
15329  
-                    pt = this.obj.points[i];
  15916
+             var faceIndices;
15330 15917
 
15331  
-                    pt[1] = w_func(pt[0], pt[2], i);
15332  
-                }
15333  
-            }
15334  
-        },
  15918
+             if (slope >= 1.0) {
  15919
+                 faceIndices = [(i) + ((j + 1) * this.divX), (i + 1) + ((j) * this.divX), (i) + ((j) * this.divX)];
  15920
+                 return [i,j,faceIndices,0];    // starting index + index tuple + offset (half quad indicator)
  15921
+             } else {
  15922
+                 faceIndices = [(i) + ((j + 1) * this.divX), (i + 1) + ((j + 1) * this.divX), (i + 1) + ((j) * this.divX)];
  15923
+                 return [i,j,faceIndices,1];
  15924
+             }             
  15925
+         },
15335 15926
 
15336  
-        getFaceAt: function (x, z) {
15337  
-            if (typeof (x) === 'object') {
15338  
-                return this.getFaceAt(x[0], x[2]);
15339  
-            }
  15927
+         getHeightValue: function (x, z) {
  15928
+             var triangle = base.triangle;
15340 15929
 
15341  
-            var ofs_w = (this.sizeX / 2.0) - ((this.sizeX / (this.divX)) / 2.0);
15342  
-            var ofs_h = (this.sizeZ / 2.0) - ((this.sizeZ / (this.divZ)) / 2.0);
  15930
+             if (typeof (x) === 'object') {
  15931
+                 return this.getHeightValue(x[0], x[2]);
  15932
+             }
15343 15933
 
15344  
-            var i = parseInt(Math.floor(((x + ofs_w) / this.sizeX) * (this.divX)), 10);
15345  
-            var j = parseInt(Math.floor(((z + ofs_h) / this.sizeZ) * (this.divZ)), 10);
  15934
+             var faceLoc = this.getIndicesAt(x, z);
15346 15935
 
15347  
-            if (i < 0) {
15348  
-                return -1;
15349  
-            }
15350  
-            if (i >= this.divX - 1) {
15351  
-                return -1;
15352  
-            }
15353  
-            if (j < 0) {
15354  
-                return -1;
15355  
-            }
15356  
-            if (j >= this.divZ - 1) {
15357  
-                return -1;
15358  
-            }
  15936
+             if (faceLoc === -1) {
  15937
+                 return 0;
  15938
+             }
15359 15939
 
15360  
-            var faceNum1 = parseInt(i + (j * (this.divX - 1)), 10) * 2;
15361  
-            var faceNum2 = parseInt(faceNum1 + 1, 10);
  15940
+             var ofs_w = (this.sizeX / 2.0) - ((this.sizeX / (this.divX)) / 2.0);
  15941
+             var ofs_h = (this.sizeZ / 2.0) - ((this.sizeZ / (this.divZ)) / 2.0);
15362 15942
 
15363  
-            var testPt = this.obj.points[this.obj.faces[faceNum1].points[0]];
  15943
+             var pointLoc = faceLoc[2];
  15944
+             var xpos = faceLoc[0]*this.cellSize-ofs_w;
  15945
+             var zpos = faceLoc[1]*this.cellSize-ofs_h;
  15946
+             var faceOfs = faceLoc[3];
  15947
+             
  15948
+             var tmpNorm;
  15949
+             
  15950
+             if (faceOfs === 0) {
  15951
+                 tmpNorm = triangle.normal(
  15952
+                      [xpos,this.hfFloatBuffer[pointLoc[0]],zpos+this.cellSize], 
  15953
+                      [xpos+this.cellSize,this.hfFloatBuffer[pointLoc[1]],zpos], 
  15954
+                      [xpos,this.hfFloatBuffer[pointLoc[2]],zpos]  
  15955
+                  );
  15956
+             } else {
  15957
+                 tmpNorm = triangle.normal(
  15958
+                      [xpos,this.hfFloatBuffer[pointLoc[0]],zpos+this.cellSize], 
  15959
+                      [xpos+this.cellSize,this.hfFloatBuffer[pointLoc[1]],zpos+this.cellSize], 
  15960
+                      [xpos+this.cellSize,this.hfFloatBuffer[pointLoc[2]],zpos]  
  15961
+                  );
  15962
+             } 
  15963
+             
  15964
+             var na = tmpNorm[0];
  15965
+             var nb = tmpNorm[1];
  15966
+             var nc = tmpNorm[2];
15364 15967
 
15365  
-            var slope = Math.abs(z - testPt[2]) / Math.abs(x - testPt[0]);
  15968
+             var tmpPoint = [xpos,this.hfFloatBuffer[pointLoc[0]],zpos+this.cellSize];
15366 15969
 
15367  
-            if (slope >= 1.0) {
15368  
-                return (faceNum1);
15369  
-            } else {
15370  
-                return (faceNum2);
15371  
-            }
15372  
-        },
  15970
+             var d = -(na * tmpPoint[0]) - (nb * tmpPoint[1]) - (nc * tmpPoint[2]);
15373 15971
 
15374  
-        getHeightValue: function (x, z) {
15375  
-            var triangle = base.triangle;
15376  
- 
15377  
-            if (typeof (x) === 'object') {
15378  
-                return this.getHeightValue(x[0], x[2]);
15379  
-            }
  15972
+             return (((na * x) + (nc * z) + d) / (-nb)); // add height ofs here
  15973
+         }
  15974
+    };
  15975
+    
  15976
+    
  15977
+    var HeightFieldMesh = base.extendClassGeneral(base.Mesh, function() {
  15978
+        var opt = arguments[0]||{};
15380 15979
 
15381  
-            var tmpFace;
15382  
-            var tmpPoint;
  15980
+        opt.dynamic = true;
  15981
+        opt.buildWireframe = true;
  15982
+        
  15983
+        this.material = opt.material;
  15984
+        
  15985
+        this._update = base.Mesh.prototype.update;
  15986
+        base.Mesh.apply(this,[opt]);
  15987
+
  15988
+        this.hField = opt.hField||null;
  15989
+        this.divX = opt.divX||null;
  15990
+        this.divZ = opt.divZ||null;
  15991
+        this.viewX = opt.viewX||0;
  15992
+        this.viewZ = opt.viewZ||0;
  15993
+        this.ofsX = opt.ofsX||0;
  15994
+        this.ofsZ = opt.ofsZ||0;
  15995
+        
  15996
+        
  15997
+        this.genHeightfieldMesh();
  15998
+        
  15999
+    },{ // subclass functions
15383 16000
 
15384  
-            var faceNum = this.getFaceAt(x, z);
  16001
+        setIndexedHeight: function (ipos, jpos, val) {
  16002
+            this.points[(ipos) + (jpos * this.divX)][1] = val;
  16003
+        },
15385 16004
 
15386  
-            if (faceNum === -1) {
15387  
-                return 0;
  16005
+        genHeightfieldMesh: function() {
  16006
+            var i, j;
  16007
+            
  16008
+            var dx = this.divX;
  16009
+            var dz = this.divZ;
  16010
+            var cellSize = this.hField.getCellSize();
  16011
+            var szx = cellSize*this.divX;
  16012
+            var szz = cellSize*this.divZ;
  16013
+
  16014
+            if (this.points.length!==0) {
  16015
+                this.clean();
15388 16016
             }
15389 16017
 
15390  
-            tmpFace = this.obj.faces[faceNum];
15391  
-            tmpPoint = this.obj.points[this.obj.faces[faceNum].points[0]];
  16018
+            for (j = -(szz / 2.0); j < (szz / 2.0); j += (szz / dz)) {
  16019
+                for (i = -(szx / 2.0); i < (szx / 2.0); i += (szx / dx)) {
  16020
+                    this.addPoint([i + ((szx / (dx)) / 2.0)+this.ofsX, 0, j + ((szz / (dz)) / 2.0)+this.ofsZ]);
  16021
+                }
  16022
+            }
15392 16023
 
15393  
-            var tmpNorm = triangle.normal(this.obj.points[this.obj.faces[faceNum].points[0]], this.obj.points[this.obj.faces[faceNum].points[1]], this.obj.points[this.obj.faces[faceNum].points[2]]);
  16024
+            var k, l;
15394 16025
 
15395  
-            var na = tmpNorm[0];
15396  
-            var nb = tmpNorm[1];
15397  
-            var nc = tmpNorm[2];
  16026
+            this.setFaceMaterial(this.material);
15398 16027
 
15399  
-            var d = -(na * tmpPoint[0]) - (nb * tmpPoint[1]) - (nc * tmpPoint[2]);
  16028
+            for (l = 0; l < dz - 1; l++) {
  16029
+                for (k = 0; k < dx - 1; k++) {
  16030
+                    this.addFace([(k) + ((l + 1) * dx), (k + 1) + ((l) * dx), (k) + ((l) * dx)]);
  16031
+                    this.addFace([(k) + ((l + 1) * dx), (k + 1) + ((l + 1) * dx), (k + 1) + ((l) * dx)]);
  16032
+                }
  16033
+            }
  16034
+        },
  16035
+        
  16036
+        update: function () {
  16037
+            var startPosX = this.viewX||0;
  16038
+            var startPosZ = this.viewZ||0;
  16039
+
  16040
+            var hfViewWidth = this.divX;
  16041
+            var hfViewDepth = this.divZ;
  16042
+            var hfWidth = this.hField.getDivX();
  16043
+            var hfDepth = this.hField.getDivZ();
  16044
+            var hField = this.hField.getFloat32Buffer();
  16045
+
  16046
+            for (var j = startPosZ, jMax = startPosZ+hfViewDepth; j<jMax; j++) { 
  16047
+                for (var i = startPosX, iMax = startPosX+hfViewWidth; i<iMax; i++) {
  16048
+                    var idx = j*hfWidth+i;
  16049
+                    var point_idx = (j-startPosZ) * hfViewWidth + (i-startPosX);
  16050
+                    var height_val = hField[idx];
  16051
+                    this.points[point_idx][1] = height_val;
  16052
+                }
  16053
+            }
15400 16054
 
15401  
-            return (((na * x) + (nc * z) + d) / (-nb)); // add height ofs here
  16055
+            this._update();
15402 16056
         }
15403  
-    };
  16057
+    });
15404 16058
 
15405 16059
     var exports = {
15406  
-        HeightField: HeightField
  16060
+        HeightField: HeightField,
  16061
+        HeightFieldBrush: HeightFieldBrush,
  16062
+        HeightFieldMesh: HeightFieldMesh
15407 16063
     };
15408 16064
 
15409 16065
     return exports;
@@ -15426,32 +16082,39 @@ CubicVR.RegisterModule("Landscape", function (base) {
15426 16082
     var Landscape = base.extendClassGeneral(base.SceneObject, function() {
15427 16083
         // args: [0]size, [1]divisions_w, [2]divisions_h, [3]matRef 
15428 16084
         // todo: fix examples for single argument constructor
15429  
-        this.heightfield = new base.HeightField({
  16085
+        this.hField = new base.HeightField({
  16086
+            size: arguments[0], 
  16087
+            divX: arguments[1], 
  16088
+            divZ: arguments[2]
  16089
+        });
  16090
+        this.hfMesh = new base.HeightFieldMesh({
  16091
+            hField: this.hField,
15430 16092
             size: arguments[0], 
15431 16093
             divX: arguments[1], 
15432 16094
             divZ: arguments[2], 
15433 16095
             material: arguments[3]
15434 16096
         });
  16097
+        this.hfMesh.prepare();
15435 16098
         
15436  
-        base.SceneObject.apply(this,[{mesh:this.heightfield.getMesh()}]);
15437  
-    },{ // subclass functions
15438  
-        setIndexedHeight: function (ipos, jpos, val) {
15439  
-            var obj = this.obj;
15440  
-            obj.points[(ipos) + (jpos * this.divisions_w)][1] = val;
  16099
+        base.SceneObject.apply(this,[{mesh:this.hfMesh,shadowCast:false}]);
  16100
+    },{ // subclass functions        
  16101
+        getHeightField: function() {
  16102
+            return this.hField;
15441 16103
         },
15442 16104
 
15443 16105
         mapGen: function (w_func, ipos, jpos, ilen, jlen) {
15444  
-           this.heightfield.mapGen({
  16106
+           this.hField.setRect({
15445 16107
                src: w_func,
15446 16108
                startX: ipos,
15447 16109
                startZ: jpos,
15448 16110
                walkX: ilen,
15449 16111
                walkZ: jlen
15450 16112
            });
  16113
+           this.hfMesh.update();
15451 16114
         },
15452 16115
 
15453 16116
         getFaceAt: function (x, z) {
15454  
-            return this.heightfield.getFaceAt([x,0,z]);
  16117
+            return this.hField.getFaceAt([x,0,z]);
15455 16118
         },
15456 16119
 
15457 16120
         getHeightValue: function (x, z, transform) {
@@ -15460,7 +16123,7 @@ CubicVR.RegisterModule("Landscape", function (base) {
15460 16123
                 // TODO: perform transformation inverse of x,0,z coordinate
15461 16124
             }
15462 16125
 
15463  
-            return this.heightfield.getHeightValue([x,0,z]);
  16126
+            return this.hField.getHeightValue([x,0,z]);
15464 16127
         },
15465 16128
 
15466 16129
         orient: function (x, z, width, length, heading, center) {
@@ -15511,6 +16174,114 @@ CubicVR.RegisterModule("Landscape", function (base) {
15511 16174
 
15512 16175
 
15513 16176
 });
  16177
+
  16178
+
  16179
+CubicVR.RegisterModule("SpatMaterial", function (base) {
  16180
+
  16181
+    var undef = base.undef;
  16182
+    var enums = base.enums;
  16183
+    var GLCore = base.GLCore;
  16184
+        
  16185
+    var vs = [
  16186
+        "void main(void) {",
  16187
+        "  vertexTexCoordOut = cubicvr_texCoord();",
  16188
+        "  gl_Position =  matrixProjection * matrixModelView * cubicvr_transform();",
  16189
+        "  #if !LIGHT_DEPTH_PASS  // not needed if shadowing ",
  16190
+        "    vertexNormalOut = matrixNormal * cubicvr_normal();",
  16191
+        "    cubicvr_lighting();",
  16192
+        "  #endif // !LIGHT_DEPTH_PASS ",
  16193
+        "}"].join("\n");
  16194
+
  16195
+    var dummyTex;
  16196
+    
  16197
+    var fs = [
  16198
+        "uniform sampler2D spatImage;",
  16199
+        "uniform sampler2D spat0;",
  16200
+        "uniform sampler2D spat1;",
  16201
+        "uniform sampler2D spat2;",
  16202
+        "uniform sampler2D spat3;",
  16203
+        "uniform sampler2D spat4;",
  16204
+        "void main(void) ",
  16205
+        "{  ",
  16206
+            "vec2 texCoord = cubicvr_texCoord();",
  16207
+            "vec4 spatSource = texture2D(spatImage,texCoord);",
  16208
+            "vec2 spatTexCoord = texCoord*10.0;",
  16209
+            "vec4 color = texture2D(spat0,spatTexCoord);",
  16210
+
  16211
+            "color = mix(color,texture2D(spat1,spatTexCoord),spatSource.r);",
  16212
+            "color = mix(color,texture2D(spat2,spatTexCoord),spatSource.g);",
  16213
+            "color = mix(color,texture2D(spat3,spatTexCoord),spatSource.b);",
  16214
+            "color = mix(color,texture2D(spat4,spatTexCoord),spatSource.a);",
  16215
+
  16216
+            "vec3 normal = cubicvr_normal(texCoord);",
  16217
+            "color = cubicvr_environment(color,normal,texCoord);",
  16218
+            "color = cubicvr_lighting(color,normal,texCoord);",
  16219
+            "gl_FragColor = clamp(color,0.0,1.0);",
  16220
+        "}"].join("\n");
  16221
+
  16222
+    // SpatMaterial extends Material
  16223
+    var SpatMaterial = base.extendClassGeneral(base.Material, function() {
  16224
+        var opt = arguments[0]||{};
  16225
+        
  16226
+        if (!dummyTex) {
  16227
+            dummyTex = new base.Texture();
  16228
+        }
  16229
+
  16230
+        this.spats = opt.spats||[dummyTex,dummyTex,dummyTex,dummyTex,dummyTex];
  16231
+        this.sourceTex = opt.sourceTexture||dummyTex; 
  16232
+                
  16233
+        var spats = this.spats;
  16234
+        var sourceTexture = this.sourceTex;
  16235
+        
  16236
+        for (var i in spats) {
  16237
+            var tex = spats[i];
  16238
+            if (typeof(tex) === "string") {
  16239
+              spats[i] = (base.Textures_ref[tex] !== undef) ? base.Textures_obj[base.Textures_ref[tex]] : (new base.Texture(tex));
  16240
+            }
  16241
+        }
  16242
+        
  16243
+        this.spatShader = new base.CustomShader({
  16244
+            vertex: vs,
  16245
+            fragment: fs,
  16246
+            init: function(shader) {    
  16247
+                
  16248
+            }, 
  16249
+            update: function(shader,opt) {
  16250
+                var material = opt.material;
  16251
+                var texIndex = opt.textureIndex;
  16252
+                
  16253
+                shader.spatImage.set(texIndex++,sourceTexture);
  16254
+
  16255
+                if (spats[0]) shader.spat0.set(texIndex++,spats[0]);
  16256
+                if (spats[1]) shader.spat1.set(texIndex++,spats[1]);
  16257
+                if (spats[2]) shader.spat2.set(texIndex++,spats[2]);
  16258
+                if (spats[3]) shader.spat3.set(texIndex++,spats[3]);
  16259
+                if (spats[4]) shader.spat4.set(texIndex++,spats[4]);
  16260
+            }
  16261
+        });
  16262
+        
  16263
+        opt.shader = this.spatShader;
  16264
+        
  16265
+        base.Material.apply(this,[opt]);
  16266
+                
  16267
+    },{ // subclass functions
  16268
+        setSpats: function(spats) {
  16269
+            this.spats = spats;
  16270
+        },
  16271
+        getSpats: function() {
  16272
+            return this.spats;
  16273
+        },
  16274
+        setSource: function(sourceTex) {
  16275
+            
  16276
+        }
  16277
+    });
  16278
+
  16279
+    var exports = {
  16280
+        SpatMaterial: SpatMaterial
  16281
+    };
  16282
+
  16283
+    return exports;
  16284
+});
15514 16285
 CubicVR.RegisterModule("Octree",function(base) {
15515 16286
 
15516 16287
   var undef = base.undef;
@@ -18846,23 +19617,23 @@ CubicVR.RegisterModule("ScenePhysics",function(base) {
18846 19617
             var points;
18847 19618
 
18848 19619
             // allow heightfield type patch-over
18849  
-            if (shape.landscape && !shape.heightfield && shape.landscape instanceof base.HeightField) {
  19620
+            if (shape.landscape && !shape.getHeightField && shape.landscape instanceof base.HeightField) {
18850 19621
                 shape.heightfield = shape.landscape;    // patch
18851 19622
             } else if (shape.landscape && shape.landscape instanceof base.Landscape) {
18852  
-              xdiv = shape.landscape.heightfield.divX;
18853  
-              zdiv = shape.landscape.heightfield.divZ;
18854  
-              xsize = shape.landscape.heightfield.sizeX;
18855  
-              zsize = shape.landscape.heightfield.sizeZ;
18856  
-              points = shape.landscape.heightfield.getMesh().points;
  19623
+              xdiv = shape.landscape.getHeightField().getDivX();
  19624
+              zdiv = shape.landscape.getHeightField().getDivZ();
  19625
+              xsize = shape.landscape.getHeightField().getSizeX();
  19626
+              zsize = shape.landscape.getHeightField().getSizeZ();
  19627
+              points = shape.landscape.getMesh().points;
18857 19628
             } 
18858 19629
             
18859 19630
             // heightfield direct
18860 19631
             if (shape.heightfield && shape.heightfield instanceof base.HeightField) {
18861  
-              xdiv = shape.heightfield.divX;
18862  
-              zdiv = shape.heightfield.divZ;
18863  
-              xsize = shape.heightfield.sizeX;
18864  
-              zsize = shape.heightfield.sizeZ;
18865  
-              points = shape.heightfield.getMesh().points;
  19632
+              xdiv = shape.heightfield.getDivX();
  19633
+              zdiv = shape.heightfield.getDivZ();
  19634
+              xsize = shape.heightfield.getSizeX();
  19635
+              zsize = shape.heightfield.getSizeZ();
  19636
+              points = shape.getMesh().points;
18866 19637
             }
18867 19638
 
18868 19639
             var upIndex = 1; 
1,118  dist/CubicVR.min.js
570 additions, 548 deletions not shown
42  samples/pdf/pdf_gallery.html
@@ -60,28 +60,28 @@
@@ -99,7 +99,7 @@
@@ -121,12 +121,12 @@
@@ -135,12 +135,12 @@
67  source/CubicVR.Camera.js
@@ -64,6 +64,73 @@ CubicVR.RegisterModule("Camera", function (base) {
64 64
     }
65 65
 
66 66
     Camera.prototype = {
  67
+        get x(){
  68
+            return this.position[0];
  69
+        },
  70
+        set x(val){
  71
+            this.position[0] = val;
  72
+        },
  73
+        get y(){
  74
+            return this.position[1];
  75
+        },
  76
+        set y(val){
  77
+            this.position[1] = val;
  78
+        },
  79
+        get z(){
  80
+            return this.position[2];
  81
+        },
  82
+        set z(val){
  83
+            this.position[2] = val;
  84
+        },
  85
+        get rotX(){
  86
+            return this.rotation[0];
  87
+        },
  88
+        set rotX(val){
  89
+            this.rotation[0] = val;
  90
+        },
  91
+        get rotY(){
  92
+            return this.rotation[1];
  93
+        },
  94
+        set rotY(val){
  95
+            this.rotation[1] = val;
  96
+        },
  97
+        get rotZ(){
  98
+            return this.rotation[2];
  99
+        },
  100
+        set rotZ(val){
  101
+            this.rotation[2] = val;
  102
+        },
  103
+        get targetX(){
  104
+            return this.target[0];
  105
+        },
  106
+        set targetX(val){
  107
+            this.target[0] = val;
  108
+        },
  109
+        get targetY(){
  110
+            return this.target[1];
  111
+        },
  112
+        set targetY(val){
  113
+            this.target[1] = val;
  114
+        },
  115
+        get targetZ(){
  116
+            return this.target[2];
  117
+        },
  118
+        set targetZ(val){
  119
+            this.target[2] = val;
  120
+        },
  121
+        get pos(){
  122
+            return this.position.slice(0);
  123
+        },        
  124
+        set pos(val){
  125
+            this.position = val.slice(0);
  126
+        },
  127
+        get rot(){
  128
+            return this.rotation.slice(0);
  129
+        },        
  130
+        set rot(val){
  131
+            this.rotation = val.slice(0);
  132
+        },
  133
+        
67 134
         trackTarget: function(targetPos, speed, safeDist) {
68 135
           this.position = base.vec3.trackTarget(this.position,targetPos,speed,safeDist);
69 136
         },
72  source/CubicVR.Light.js
@@ -117,6 +117,78 @@ CubicVR.RegisterModule("Light", function (base) {
117 117
     }
118 118
 
119 119
     Light.prototype = {
  120
+        get x(){
  121
+            return this.position[0];
  122
+        },
  123
+        set x(val){
  124
+            this.position[0] = val;
  125
+        },
  126
+        get y(){
  127
+            return this.position[1];
  128
+        },
  129
+        set y(val){
  130
+            this.position[1] = val;
  131
+        },
  132
+        get z(){
  133
+            return this.position[2];
  134
+        },
  135
+        set z(val){
  136
+            this.position[2] = val;
  137
+        },
  138
+        get rotX(){
  139
+            return this.rotation[0];
  140
+        },
  141
+        set rotX(val){
  142
+            this.rotation[0] = val;
  143
+        },
  144
+        get rotY(){
  145
+            return this.rotation[1];
  146
+        },
  147
+        set rotY(val){
  148
+            this.rotation[1] = val;
  149
+        },
  150
+        get rotZ(){
  151
+            return this.rotation[2];
  152
+        },
  153
+        set rotZ(val){
  154
+            this.rotation[2] = val;
  155
+        },
  156
+        get dirX(){
  157
+            return this.direction[0];
  158
+        },
  159
+        set dirX(val){
  160
+            this.direction[0] = val;
  161
+        },
  162
+        get dirY(){
  163
+            return this.direction[1];
  164
+        },
  165
+        set dirY(val){
  166
+            this.direction[1] = val;
  167
+        },
  168
+        get dirZ(){
  169
+            return this.direction[2];
  170
+        },
  171
+        set dirZ(val){
  172
+            this.direction[2] = val;
  173
+        },
  174
+        get pos(){
  175
+            return this.position.slice(0);
  176
+        },        
  177
+        set pos(val){
  178
+            this.position = val.slice(0);
  179
+        },
  180
+        get rot(){
  181
+            return this.rotation.slice(0);
  182
+        },        
  183
+        set rot(val){
  184
+            this.rotation = val.slice(0);
  185
+        },
  186
+        get dir(){
  187
+            return this.direction.slice(0);
  188
+        },        
  189
+        set dir(val){
  190
+            this.direction = vec3.normalize(val.slice(0));
  191
+        },
120 192
         setType: function (light_type) {
121 193
             if (light_type === enums.light.type.AREA && !base.features.lightShadows) {
122 194
                 this.dummyCam = new base.Camera();
74  source/CubicVR.Scene.js
@@ -95,7 +95,79 @@ CubicVR.RegisterModule("Scene", function (base) {
95 95