Skip to content

Commit

Permalink
Scenegraph visitor system for rendering and material overrides.
Browse files Browse the repository at this point in the history
  • Loading branch information
dnadlinger committed Oct 25, 2009
1 parent 32c6b2a commit dfca2e4
Show file tree
Hide file tree
Showing 13 changed files with 221 additions and 170 deletions.
26 changes: 13 additions & 13 deletions src/SpinningLights.d
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,11 @@ import d4.renderer.IMaterial;
import d4.renderer.IRasterizer;
import d4.renderer.Renderer;
import d4.renderer.SolidRasterizer;
import d4.scene.CollectPointsVisitor;
import d4.scene.Mesh;
import d4.scene.Node;
import d4.scene.Primitives;
import d4.scene.FixedMaterialRenderVisitor;
import d4.scene.Vertex;
import d4.util.ArrayUtils;
import d4.util.FreeCameraApplication;
Expand Down Expand Up @@ -148,26 +150,24 @@ protected:
makeCube( Vector3( -8, 0, -8 ), Vector3( 8, 8, 8 ), true ) );
} else if ( m_displayRoom ) {
// Compute the bounding box of the scene geometry.
Vertex[] vertices = m_rootNode.flatten().
map( ( Mesh m ){ return m.vertices; } ).flatten();
AABB boundingBox = AABB( vertices.map( ( Vertex v ){ return v.position; } ) );
auto collector = new CollectPointsVisitor();
m_rootNode.accept( collector );

AABB boundingBox = AABB( collector.result );

// Enlarge the box 5 units to the sides, 3 to the top, and 0 to the
// bottom.
boundingBox.enlarge( Vector3( 5, 3, 5 ) );
boundingBox.min.y += 3;

m_rootNode.addMesh( makeCube( boundingBox, true ) );
}

// TODO: Add global material override function to material manager instead?
m_material = new Material();
auto allMeshes = m_rootNode.flatten();
foreach ( mesh; allMeshes ) {
mesh.material = m_material;
auto newRoot = new Node();
newRoot.addMesh( makeCube( boundingBox, true ) );
newRoot.addChild( m_rootNode );
m_rootNode = newRoot;
}

cameraPosition = Vector3( 0, 3, 5 );
m_material = new Material();
}

override void render( float deltaTime ) {
Expand All @@ -176,7 +176,7 @@ protected:
m_material.updatePositions( deltaTime );

renderer().beginScene();
m_rootNode.render( renderer() );
m_rootNode.accept( new FixedMaterialRenderVisitor( renderer(), m_material ) );
renderer().endScene();
}

Expand All @@ -199,7 +199,7 @@ protected:
if ( values.length > 0 ) {
// Call the superclass function first to get a nice error message for
// too many arguments if loading the scene fails.
super.handleUnnamedArguments( values[ 0..($-1) ] );
super.handleUnnamedArguments( values[ 0..( $ - 1 ) ] );
m_rootNode = ( new AssimpScene( values[ $ - 1 ] ) ).rootNode;
}
}
Expand Down
69 changes: 68 additions & 1 deletion src/Viewer.d
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,30 @@ import d4.math.Color;
import d4.math.Matrix4;
import d4.math.Quaternion;
import d4.math.Transformations;
import d4.renderer.IMaterial;
import d4.renderer.SolidRasterizer;
import d4.scene.BasicMaterial;
import d4.scene.ISceneVisitor;
import d4.scene.Node;
import d4.scene.Scene;
import d4.scene.FixedMaterialRenderVisitor;
import d4.scene.RenderVisitor;
import d4.scene.Vertex;
import d4.shader.LitSingleColorShader;
import d4.shader.SingleColorShader;
import d4.util.FreeCameraApplication;
import d4.util.Key;
import util.EntryPoint;

/**
* The available shading modes.
*/
enum ShadingMode {
FLAT,
GOURAUD,
GOURAUD_TEXTURED
}

/**
* The main application class.
* Manages the scene, reacts to user input, etc.
Expand All @@ -48,6 +65,21 @@ protected:
m_animateBackground = false;
m_backgroundTime = 0;
renderer().clearColor = Color( 0, 0, 0 );

// Enable everything by default.
m_shadingMode = ShadingMode.GOURAUD_TEXTURED;
m_forceWireframe = false;

m_wireframeMaterial = new BasicMaterial();
m_wireframeMaterial.wireframe = true;

m_flatMaterial = new BasicMaterial();
m_flatMaterial.gouraudShading = false;
m_flatMaterial.lighting = true;

m_gouraudMaterial = new BasicMaterial();
m_gouraudMaterial.vertexColors = false;
m_gouraudMaterial.lighting = true;
}

override void render( float deltaTime ) {
Expand All @@ -60,8 +92,29 @@ protected:
updateRotatingWorld( deltaTime );
}

ISceneVisitor renderVisitor;

if ( m_forceWireframe ) {
renderVisitor = new FixedMaterialRenderVisitor(
renderer(), m_wireframeMaterial );
} else {
switch ( m_shadingMode ) {
case ShadingMode.FLAT:
renderVisitor = new FixedMaterialRenderVisitor(
renderer(), m_flatMaterial );
break;
case ShadingMode.GOURAUD:
renderVisitor = new FixedMaterialRenderVisitor(
renderer(), m_gouraudMaterial );
break;
case ShadingMode.GOURAUD_TEXTURED:
renderVisitor = new RenderVisitor( renderer() );
break;
}
}

renderer().beginScene();
m_scene.rootNode.render( renderer() );
m_scene.rootNode.accept( renderVisitor );
renderer().endScene();
}

Expand All @@ -73,6 +126,13 @@ protected:
super.handleKeyUp( key );

switch ( key ) {
case Key.y:
case Key.z:
m_shadingMode = cast( ShadingMode )( ( m_shadingMode + 1 ) % ( m_shadingMode.max + 1 ) );
break;
case Key.x:
m_forceWireframe = !m_forceWireframe;
break;
case Key.v:
m_rotateWorld = !m_rotateWorld;
break;
Expand Down Expand Up @@ -133,6 +193,13 @@ private:

Scene m_scene;

ShadingMode m_shadingMode;
bool m_forceWireframe;

BasicMaterial m_wireframeMaterial;
BasicMaterial m_flatMaterial;
BasicMaterial m_gouraudMaterial;

bool m_rotateWorld;
bool m_animateBackground;
float m_backgroundTime;
Expand Down
2 changes: 1 addition & 1 deletion src/d4/output/SdlSurface.d
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public:
override uint height() {
return m_sdlSurface.h;
}

override void lock() {
super.lock();
if ( m_mustLock ) {
Expand Down
71 changes: 6 additions & 65 deletions src/d4/renderer/Renderer.d
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
module d4.renderer.Renderer;

import d4.shader.SingleColorShader;
import tango.math.Math : PI;
import tango.util.container.HashMap;
import d4.math.Color;
Expand All @@ -16,7 +15,6 @@ import d4.renderer.SolidRasterizer;
import d4.renderer.WireframeRasterizer;
import d4.renderer.ZBuffer;
import d4.scene.Vertex;
import d4.shader.LitSingleColorShader;
import d4.shader.SingleColorShader;

alias d4.renderer.IRasterizer.BackfaceCulling BackfaceCulling;
Expand All @@ -41,11 +39,7 @@ public:
m_zBuffer = new ZBuffer( renderTarget.width, renderTarget.height );
m_clearColor = Color( 0, 0, 0 );

m_whiteFlatRasterizer = new SolidRasterizer!( false, LitSingleColorShader, 0.1, 1, -1, -1 )();
m_whiteGouraudRasterizer = new SolidRasterizer!( true, LitSingleColorShader, 0.1, 1, -1, -1 )();
m_whiteWireframeRasterizer = new WireframeRasterizer!( SingleColorShader );

m_activeRasterizer = m_whiteFlatRasterizer;
m_activeRasterizer = new WireframeRasterizer!( SingleColorShader );
m_activeRasterizer.setRenderTarget( m_renderTarget, m_zBuffer );
setProjection( PI / 2, 0.1f, 100.f );

Expand Down Expand Up @@ -105,20 +99,12 @@ public:
* material = The material to activate.
*/
void activateMaterial( IMaterial material ) {
if ( m_forceWireframe ) {
activateRasterizer( m_whiteWireframeRasterizer );
} else if ( m_forceFlatShading ) {
activateRasterizer( m_whiteFlatRasterizer );
} else if ( m_skipTextures && material.usesTextures() ) {
activateRasterizer( m_whiteGouraudRasterizer );
} else {
if ( !m_materialRasterizers.containsKey( material ) ) {
m_materialRasterizers.add( material, material.getRasterizer() );
}

activateRasterizer( m_materialRasterizers[ material ] );
material.prepareForRendering( this );
if ( !m_materialRasterizers.containsKey( material ) ) {
m_materialRasterizers.add( material, material.getRasterizer() );
}

activateRasterizer( m_materialRasterizers[ material ] );
material.prepareForRendering( this );
}


Expand Down Expand Up @@ -187,43 +173,6 @@ public:
m_clearColor = clearColor;
}

/**
* Causes all materials to be rendered as if their wireframe property was set.
*/
bool forceWireframe() {
return m_forceWireframe;
}

/// ditto
void forceWireframe( bool forceWireframe ) {
m_forceWireframe = forceWireframe;
}

/**
* Causes all materials to be rendered as if gouraud shading was not enabled
* for them.
*/
bool forceFlatShading() {
return m_forceFlatShading;
}

/// ditto
void forceFlatShading( bool forceFlatShading ) {
m_forceFlatShading = forceFlatShading;
}

/**
* Replaces all textured materials with a generic textureless one.
*/
bool skipTextures() {
return m_skipTextures;
}

/// ditto
void skipTextures( bool skipTextures ) {
m_skipTextures = skipTextures;
}

private:
void activateRasterizer( IRasterizer rasterizer ) {
if ( rasterizer == m_activeRasterizer ) {
Expand All @@ -246,14 +195,6 @@ private:
MaterialRasterizerMap m_materialRasterizers;
IRasterizer m_activeRasterizer;

IRasterizer m_whiteFlatRasterizer;
IRasterizer m_whiteGouraudRasterizer;
IRasterizer m_whiteWireframeRasterizer;

Surface m_renderTarget;
ZBuffer m_zBuffer;

bool m_forceWireframe;
bool m_forceFlatShading;
bool m_skipTextures;
}
32 changes: 32 additions & 0 deletions src/d4/scene/CollectPointsVisitor.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
module d4.scene.CollectPointsVisitor;

import d4.math.Vector3;
import d4.math.Matrix4;
import d4.scene.ISceneVisitor;
import d4.scene.Mesh;
import d4.scene.Node;

class CollectPointsVisitor : ISceneVisitor {
public:
this() {
m_result = [];
}

void visitNode( Node node ) {
m_currentWorldMatrix = node.worldMatrix();
}

void visitMesh( Mesh mesh ) {
foreach ( vertex; mesh.vertices ) {
m_result ~= m_currentWorldMatrix.transformLinear( vertex.position );
}
}

Vector3[] result() {
return m_result;
}

private:
Vector3[] m_result;
Matrix4 m_currentWorldMatrix;
}
28 changes: 28 additions & 0 deletions src/d4/scene/FixedMaterialRenderVisitor.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
module d4.scene.FixedMaterialRenderVisitor;

import d4.renderer.IMaterial;
import d4.renderer.Renderer;
import d4.scene.ISceneVisitor;
import d4.scene.Mesh;
import d4.scene.Node;

class FixedMaterialRenderVisitor : ISceneVisitor {
public:
this( Renderer renderer, IMaterial material ) {
m_renderer = renderer;
m_material = material;
}

void visitNode( Node node ) {
m_renderer.worldMatrix = node.worldMatrix;
}

void visitMesh( Mesh mesh ) {
m_renderer.activateMaterial( m_material );
m_renderer.renderTriangleList( mesh.vertices, mesh.indices );
}

private:
Renderer m_renderer;
IMaterial m_material;
}
7 changes: 7 additions & 0 deletions src/d4/scene/ISceneElement.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
module d4.scene.ISceneElement;

import d4.scene.ISceneVisitor;

interface ISceneElement {
void accept( ISceneVisitor visitor );
}
9 changes: 9 additions & 0 deletions src/d4/scene/ISceneVisitor.d
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module d4.scene.ISceneVisitor;

import d4.scene.Mesh;
import d4.scene.Node;

interface ISceneVisitor {
void visitMesh( Mesh mesh );
void visitNode( Node node );
}
Loading

0 comments on commit dfca2e4

Please sign in to comment.