Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
36 commits
Select commit Hold shift + click to select a range
6cdd3a0
base
Feb 7, 2017
d4b0c11
Basecode for buildings
Feb 10, 2017
a0c5b38
skybox added
Feb 10, 2017
d14b9ef
About to try moving code to shape.js
Feb 10, 2017
a563881
trying to organize and share variables across classes
Feb 11, 2017
f8091c9
got subdivision and scaling
Feb 15, 2017
b76cca8
save
Feb 15, 2017
cd3dc90
save1
Feb 15, 2017
fdf32d7
save3
Feb 15, 2017
874e957
bloack made
Feb 15, 2017
ed23f3e
The geometry is finally being loaded in correctly. hallelujah!!!!
Feb 15, 2017
599e105
almost have windows
Feb 15, 2017
cf55429
i hath windows!!! yaaaasss
Feb 15, 2017
6cfe8cd
all windows !!
Feb 16, 2017
d51b3b7
have doors!
Feb 16, 2017
0a72015
Better doors
Feb 16, 2017
4965a14
Moving on to city building
Feb 16, 2017
630e79e
city gui complete
Feb 16, 2017
9308337
saving
Feb 16, 2017
323bcf7
some spline
Feb 16, 2017
6ac8331
saved
Feb 16, 2017
6c38c1b
basic city layout made
Feb 16, 2017
1d96ea0
have a city like thing sorta
Feb 16, 2017
16f4777
better city layout
Feb 16, 2017
9525260
Praise the pretzel
Feb 17, 2017
4c90ceb
glados
AmanSachan1 Feb 17, 2017
32a9a86
praise the sun
AmanSachan1 Feb 17, 2017
61ad953
trying to deploy
AmanSachan1 Mar 8, 2017
6a6d077
cleaned and commented
AmanSachan1 Mar 10, 2017
38fe39a
readme update
AmanSachan1 Oct 6, 2017
c9f9ba1
readme update
AmanSachan1 Oct 6, 2017
3b910cc
readme update - shape grammar intro
AmanSachan1 Oct 6, 2017
dfeacf2
readme update - shape grammar intro
AmanSachan1 Oct 6, 2017
5e369bd
readme update - shape grammar intro
AmanSachan1 Oct 6, 2017
f617472
readme update - shape grammar intro
AmanSachan1 Oct 6, 2017
2417443
readme update - shape grammar intro
AmanSachan1 Oct 6, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
node_modules
npm-debug.log
95 changes: 61 additions & 34 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,45 +1,72 @@
# Dynamic Procedural City

# Project 4: Shape Grammar
[![](images/readme/ProceduralCity_vimeoLink.png)](https://vimeo.com/231604217)

For this assignment you'll be building directly off of Project 3. To make things easier to keep track of, please fork and clone this repository [https://github.com/CIS700-Procedural-Graphics/Project4-Shape-Grammar](https://github.com/CIS700-Procedural-Graphics/Project4-Shape-Grammar) and copy your Project 3 code to start.
## Overview

**Goal:** to model an urban environment using a shape grammar.
A procedural city built using shape grammar; The city is dynamic and changes with every build.

**Note:** We’re well aware that a nice-looking procedural city is a lot of work for a single week. Focus on designing a nice building grammar. The city layout strategies outlined in class (the extended l-systems) are complex and not expected. We will be satisfied with something reasonably simple, just not a uniform grid!
## Introduction to Shape Grammar

## Symbol Node (5 points)
Modify your symbol node class to include attributes necessary for rendering, such as
- Associated geometry instance
- Position
- Scale
- Anything else you may need
Shape grammars in computation are a specific class of production systems that generate geometric shapes. They are very similar to L-Systems but the grammar production process and rendering instructions are more intertwined.
- Symbols have numeric attributes, eg. position, scale
- Successors are computed, based on the numeric attributes of their predecessor, instead of just being predetermined
- Since transformation information is usually stored, symbol ordering is not necessarily important

## Grammar design (55 points)
- Design at least five shape grammar rules for producing procedural buildings. Your buildings should vary in geometry and decorative features (beyond just differently-scaled cubes!). At least some of your rules should create child geometry that is in some way dependent on its parent’s state. (20 points)
- Eg. A building may be subdivided along the x, y, or z axis into two smaller buildings
- Some of your rules must be designed to use some property about its location. (10 points)
- Your grammar should have some element of variation so your buildings are non-deterministic. Eg. your buildings sometimes subdivide along the x axis, and sometimes the y. (10 points)
- Write a renderer that will interpret the results of your shape grammar parser and adds the appropriate geometry to your scene for each symbol in your set. (10 points)
#### Basic Layout of shape grammar systems:

## Create a city (30 points)
- Add a ground plane or some other base terrain to your scene (0 points, come on now)
- Using any strategy you’d like, procedurally generate features that demarcate your city into different areas in an interesting and plausible way (Just a uniform grid is neither interesting nor plausible). (20 points)
- Suggestions: roads, rivers, lakes, parks, high-population density
- Note, these features don’t have to be directly visible, like high-population density, but they should somehow be visible in the appearance or arrangement of your buildings. Eg. High population density is more likely to generate taller buildings
- Generate buildings throughout your city, using information about your city’s features. Color your buildings with a method that uses some aspect of its state. Eg. Color buildings by height, by population density, by number of rules used to generate it. (5 points)
- Document your grammar rules and general approach in the readme. (5 points)
- ???
- Profit.
###### Symbol = {terminal, non-terminal}
###### Shape = {symbol, geometry, numeric attributes}
###### Rule = {predecessor, successor = f(predecessor), probability}

## Make it interesting (10)
Experiment! Make your city a work of art.
1. Begin with some configuration of shapes (like an l-system axiom)
2. Select an shape S from set.
3. Choose a production rule with S as predecessor, compute successor(s) S_new, and add it to the set.
4. Remove S from the set.
5. Repeat until all shapes in the set are terminal.

#### Example

## Warnings:
You can very easily blow up three.js with this assignment. With a very simple grammar, our medium quality machine was able to handle 100 buildings with 6 generations each, but be careful if you’re doing this all CPU-side.
Describing a simple building with some basic rules.
- temple -> Subdiv(“Y”, …, … } { podium | columns | roof }
- column -> Subdiv(“Y”, …){ base | shaft | capital }
- columns -> Repeat(“X”, …){ column }
- base -> (corinthian_base)
- shaft -> (corinthian_shaft)
- capital -> (corinthian_capital)
- podium -> (podium)
- roof -> (roof)

## Suggestions for the overachievers:
Go for a very high level of decorative detail!
Place buildings with a strategy such that buildings have doors and windows that are always accessible.
Generate buildings with coherent interiors
If dividing your city into lots, generate odd-shaped lots and create building meshes that match their shape ie. rather than working with cubes, extrude upwards from the building footprints you find to generate a starting mesh to subdivide rather than starting with platonic geometry.
![](images/readme/shapeGrammarTemple.png)

## Project details

The project goes about creating a city, which is created anew every time an item of the gui is updated.
Every building is modeled procedurally based on shape grammar rules and the city layout is similarly randomized.
Various GUI controls were added to give the project more life.

### GUI controls:
- Change the position that the city will spawn around.
- Change the number of iterations over the shape grammar rule applied to buildings.
- Change the density of the city.
- Change the field of view of the camera.

### Talking points for the Algorithm
- Create multiple layers of circles of increasing size centered at the same point.
- Have major roads along alternate segments joining these circles. Permanent roads.
- Have minor roads be created randomly that connect various arcs of circles.
- Place buildings inside the circles in between roads.

### Shape Grammar rules
- Subdivide buildings randomly about x or z axis
- Scale every building randomly
- Place windows on buildings depending upon the length and width of the building. And The windows are all above the ground floor.
- Add a door randomly on one of the faces of the building and randomly jitter its position along that wall.
- Add roof tops to buildings, depending on the shape and size of the buildings.
- Give every building a random color.
- All features added after the main cube building structure are shaded based on position.


## References:

- https://cis700-procedural-graphics.github.io/files/shape_grammar_2_7_17.pdf
38 changes: 38 additions & 0 deletions deploy.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
var colors = require('colors');
var path = require('path');
var git = require('simple-git')(__dirname);
var deploy = require('gh-pages-deploy');
var packageJSON = require('require-module')('./package.json');

var success = 1;
git.fetch('origin', 'master', function(err) {
if (err) throw err;
git.status(function(err, status) {
if (err) throw err;
if (!status.isClean()) {
success = 0;
console.error('Error: You have uncommitted changes! Please commit them first'.red);
}

if (status.current !== 'master') {
success = 0;
console.warn('Warning: Please deploy from the master branch!'.yellow)
}

git.diffSummary(['origin/master'], function(err, diff) {
if (err) throw err;

if (diff.files.length || diff.insertions || diff.deletions) {
success = 0;
console.error('Error: Current branch is different from origin/master! Please push all changes first'.red)
}

if (success) {
var cfg = packageJSON['gh-pages-deploy'] || {};
var buildCmd = deploy.getFullCmd(cfg);
deploy.displayCmds(deploy.getFullCmd(cfg));
deploy.execBuild(buildCmd, cfg);
}
})
})
})
71 changes: 71 additions & 0 deletions framework.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
const THREE = require('three');
const OrbitControls = require('three-orbit-controls')(THREE)
import Stats from 'stats-js'
import DAT from 'dat-gui'

// when the scene is done initializing, the function passed as `callback` will be executed
// then, every frame, the function passed as `update` will be executed
function init(callback, update) {
var stats = new Stats();
stats.setMode(1);
stats.domElement.style.position = 'absolute';
stats.domElement.style.left = '0px';
stats.domElement.style.top = '0px';
document.body.appendChild(stats.domElement);

var gui = new DAT.GUI();

var framework = {
gui: gui,
stats: stats
};

// run this function after the window loads
window.addEventListener('load', function() {

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera( 75, window.innerWidth/window.innerHeight, 0.1, 1000 );
var renderer = new THREE.WebGLRenderer( { antialias: true } );
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(window.innerWidth, window.innerHeight);
renderer.setClearColor(0x020202, 0);

var controls = new OrbitControls(camera, renderer.domElement);
controls.enableDamping = true;
controls.enableZoom = true;
controls.target.set(0, 0, 0);
controls.rotateSpeed = 0.3;
controls.zoomSpeed = 1.0;
controls.panSpeed = 2.0;

document.body.appendChild(renderer.domElement);

// resize the canvas when the window changes
window.addEventListener('resize', function() {
camera.aspect = window.innerWidth / window.innerHeight;
camera.updateProjectionMatrix();
renderer.setSize(window.innerWidth, window.innerHeight);
}, false);

// assign THREE.js objects to the object we will return
framework.scene = scene;
framework.camera = camera;
framework.renderer = renderer;

// begin the animation loop
(function tick() {
stats.begin();
update(framework); // perform any requested updates
renderer.render(scene, camera); // render the scene
stats.end();
requestAnimationFrame(tick); // register to call this again when the browser renders a new frame
})();

// we will pass the scene, gui, renderer, camera, etc... to the callback function
return callback(framework);
});
}

export default {
init: init
}
Loading