Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /**
- * @fileoverview Terrain - A simple 3D terrain using WebGL
- * @author Eric Shaffer
- */
- /** Class implementing 3D terrain. */
- class Terrain{
- /**
- * Initialize members of a Terrain object
- * @param {number} div Number of triangles along x axis and y axis
- * @param {number} minX Minimum X coordinate value
- * @param {number} maxX Maximum X coordinate value
- * @param {number} minY Minimum Y coordinate value
- * @param {number} maxY Maximum Y coordinate value
- */
- constructor(div,minX,maxX,minY,maxY){
- this.div = div;
- this.minX=minX;
- this.minY=minY;
- this.maxX=maxX;
- this.maxY=maxY;
- this.size = div+1;
- this.max = this.size-1;
- this.map = new Float32Array(this.size * this.size);
- // Allocate vertex array
- this.vBuffer = [];
- // Allocate triangle array
- this.fBuffer = [];
- // Allocate normal array
- this.nBuffer = [];
- // Allocate array for edges so we can draw wireframe
- this.eBuffer = [];
- console.log("Terrain: Allocated buffers");
- this.generateHeightMap(0.001);
- console.log("Terrain: Generated Heightmap");
- this.generateTriangles();
- console.log("Terrain: Generated triangles");
- this.generateLines();
- console.log("Terrain: Generated lines");
- // Get extension for 4 byte integer indices for drwElements
- var ext = gl.getExtension('OES_element_index_uint');
- if (ext ==null){
- alert("OES_element_index_uint is unsupported by your browser and terrain generation cannot proceed.");
- }
- }
- /**
- * Set the x,y,z coords of a vertex at location(i,j)
- * @param {Object} v an an array of length 3 holding x,y,z coordinates
- * @param {number} i the ith row of vertices
- * @param {number} j the jth column of vertices
- */
- setVertex(v,i,j)
- {
- //Your code here
- var vid = 3*(i*(this.div+1) + j);
- this.vbuffer[vid] = v[0];
- this.vbuffer[vid+1] = v[1];
- this.vbuffer[vid+2] = v[2];
- }
- /**
- * Return the x,y,z coordinates of a vertex at location (i,j)
- * @param {Object} v an an array of length 3 holding x,y,z coordinates
- * @param {number} i the ith row of vertices
- * @param {number} j the jth column of vertices
- */
- getVertex(v,i,j)
- {
- //Your code here
- var vid = 3*(i*(this.div+1) + j);
- v[0] = this.vbuffer[vid];
- v[1] = this.vbuffer[vid+1];
- v[2] = this.vbuffer[vid+2];
- }
- /**
- * Send the buffer objects to WebGL for rendering
- */
- loadBuffers()
- {
- // Specify the vertex coordinates
- this.VertexPositionBuffer = gl.createBuffer();
- gl.bindBuffer(gl.ARRAY_BUFFER, this.VertexPositionBuffer);
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(this.vBuffer), gl.STATIC_DRAW);
- this.VertexPositionBuffer.itemSize = 3;
- this.VertexPositionBuffer.numItems = this.numVertices;
- console.log("Loaded ", this.VertexPositionBuffer.numItems, " vertices");
- // Specify normals to be able to do lighting calculations
- this.VertexNormalBuffer = gl.createBuffer();
- gl.bindBuffer(gl.ARRAY_BUFFER, this.VertexNormalBuffer);
- gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(this.nBuffer),
- gl.STATIC_DRAW);
- this.VertexNormalBuffer.itemSize = 3;
- this.VertexNormalBuffer.numItems = this.numVertices;
- console.log("Loaded ", this.VertexNormalBuffer.numItems, " normals");
- // Specify faces of the terrain
- this.IndexTriBuffer = gl.createBuffer();
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.IndexTriBuffer);
- gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint32Array(this.fBuffer),
- gl.STATIC_DRAW);
- this.IndexTriBuffer.itemSize = 1;
- this.IndexTriBuffer.numItems = this.fBuffer.length;
- console.log("Loaded ", this.numFaces, " triangles");
- //Setup Edges
- this.IndexEdgeBuffer = gl.createBuffer();
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.IndexEdgeBuffer);
- gl.bufferData(gl.ELEMENT_ARRAY_BUFFER, new Uint32Array(this.eBuffer),
- gl.STATIC_DRAW);
- this.IndexEdgeBuffer.itemSize = 1;
- this.IndexEdgeBuffer.numItems = this.eBuffer.length;
- console.log("triangulatedPlane: loadBuffers");
- }
- /**
- * Render the triangles
- */
- drawTriangles(){
- gl.bindBuffer(gl.ARRAY_BUFFER, this.VertexPositionBuffer);
- gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.VertexPositionBuffer.itemSize,
- gl.FLOAT, false, 0, 0);
- // Bind normal buffer
- gl.bindBuffer(gl.ARRAY_BUFFER, this.VertexNormalBuffer);
- gl.vertexAttribPointer(shaderProgram.vertexNormalAttribute,
- this.VertexNormalBuffer.itemSize,
- gl.FLOAT, false, 0, 0);
- //Draw
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.IndexTriBuffer);
- gl.drawElements(gl.TRIANGLES, this.IndexTriBuffer.numItems, gl.UNSIGNED_INT,0);
- }
- /**
- * Render the triangle edges wireframe style
- */
- drawEdges(){
- gl.bindBuffer(gl.ARRAY_BUFFER, this.VertexPositionBuffer);
- gl.vertexAttribPointer(shaderProgram.vertexPositionAttribute, this.VertexPositionBuffer.itemSize,
- gl.FLOAT, false, 0, 0);
- // Bind normal buffer
- gl.bindBuffer(gl.ARRAY_BUFFER, this.VertexNormalBuffer);
- gl.vertexAttribPointer(shaderProgram.vertexNormalAttribute,
- this.VertexNormalBuffer.itemSize,
- gl.FLOAT, false, 0, 0);
- //Draw
- gl.bindBuffer(gl.ELEMENT_ARRAY_BUFFER, this.IndexEdgeBuffer);
- gl.drawElements(gl.LINES, this.IndexEdgeBuffer.numItems, gl.UNSIGNED_INT,0);
- }
- /**
- * Fill the vertex and buffer arrays
- */
- generateTriangles()
- {
- //Your code here
- var x_amount = (this.maxX - this.minX) / this.div;
- var y_amount = (this.maxY - this.minY) / this.div;
- for (var i = 0; i <= this.div; i++) {
- for (var j = 0; j <= this.div; j++) {
- this.vBuffer.push(j*x_amount + this.minX);
- this.vBuffer.push(this.minY + i*y_amount);
- this.vBuffer.push(this.getHeightMap(i,j)+0.5);
- this.nBuffer.push(0);
- this.nBuffer.push(0);
- this.nBuffer.push(1);
- }
- }
- for (var i = 0; i < this.div; i++) {
- for (var j = 0; j < this.div; j++) {
- var vid = i*(this.div+1) + j;
- this.fBuffer.push(vid);
- this.fBuffer.push(vid + this.div+1);
- this.fBuffer.push(vid + this.div+2);
- this.fBuffer.push(vid);
- this.fBuffer.push(vid+1);
- this.fBuffer.push(vid + this.div+2);
- }
- }
- this.numVertices = this.vBuffer.length/3;
- this.numFaces = this.fBuffer.length/3;
- }
- generateHeightMap(roughness)
- {
- this.setHeightMap(0 ,0 ,Math.random() *-1);
- this.setHeightMap(this.max,0 ,Math.random() * 0);
- this.setHeightMap(this.max,this.max,Math.random() *-1);
- this.setHeightMap(0 ,this.max,Math.random() * 1);
- this.diamondSquare(this.max, roughness);
- }
- diamondSquare(size, roughness)
- {
- var x, y, half = size / 2;
- var scale = roughness * size;
- if (half < 1) return;
- for (y = half; y < this.max; y += size) {
- for (x = half; x < this.max; x += size) {
- this.diamond(x, y, half, Math.random() * scale * 2 - scale);
- }
- }
- for (y = 0; y <= this.max; y += half) {
- for (x = (y + half) % size; x <= this.max; x += size) {
- this.square(x, y, half, Math.random() * scale * 2 - scale);
- }
- }
- this.diamondSquare(size / 2, roughness);
- }
- square(x, y, size, offset) {
- var top = this.getHeightMap(x ,y - size); // top
- var right = this.getHeightMap(x + size,y ); // right
- var bottom = this.getHeightMap(x ,y + size); // bottom
- var left = this.getHeightMap(x - size,y ); // left
- var ave = (top + right + bottom + left) / 4;
- this.setHeightMap(x, y, ave + offset);
- }
- diamond(x, y, size, offset) {
- var ul = this.getHeightMap(x - size,y - size); // upper left
- var ur = this.getHeightMap(x + size,y - size); // upper right
- var lr = this.getHeightMap(x + size,y + size); // lower right
- var ll = this.getHeightMap(x - size,y + size); // lower left
- var ave = (ul + ur + lr + ll) / 4;
- this.setHeightMap(x, y, ave + offset);
- }
- getHeightMap(x, y)
- {
- if (x < 0 || x > this.max || y < 0 || y > this.max) return -1;
- return this.map[x + this.size * y];
- }
- setHeightMap(x, y, val)
- {
- this.map[x + this.size * y] = val;
- }
- /**
- * Print vertices and triangles to console for debugging
- */
- printVBuffer()
- {
- for(var i=0;i<this.numVertices;i++) {
- console.log("v ", this.vBuffer[i*3], " ",
- this.vBuffer[i*3 + 1], " ",
- this.vBuffer[i*3 + 2], " ");
- }
- }
- printFBuffer()
- {
- for(var i=0;i<this.numFaces;i++) {
- console.log("f ", this.fBuffer[i*3], " ",
- this.fBuffer[i*3 + 1], " ",
- this.fBuffer[i*3 + 2], " ");
- }
- }
- /**
- * Generates line values from faces in faceArray
- * to enable wireframe rendering
- */
- generateLines()
- {
- var numTris=this.fBuffer.length/3;
- for(var f=0;f<numTris;f++)
- {
- var fid=f*3;
- this.eBuffer.push(this.fBuffer[fid]);
- this.eBuffer.push(this.fBuffer[fid+1]);
- this.eBuffer.push(this.fBuffer[fid+1]);
- this.eBuffer.push(this.fBuffer[fid+2]);
- this.eBuffer.push(this.fBuffer[fid+2]);
- this.eBuffer.push(this.fBuffer[fid]);
- }
- }
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement