001/**
002 * Copyright (c) 2008-2014 Ardor Labs, Inc.
003 * 
004 * This file is part of Ardor3D.
005 * 
006 * Ardor3D is free software: you can redistribute it and/or modify it under the terms of its license which may be found
007 * in the accompanying LICENSE file or at <http://www.ardor3d.com/LICENSE>.
008 */
009
010package com.ardor3d.util.scenegraph;
011
012import com.ardor3d.bounding.BoundingVolume;
013import com.ardor3d.renderer.Camera;
014import com.ardor3d.renderer.ContextManager;
015import com.ardor3d.renderer.RenderContext;
016import com.ardor3d.renderer.Renderer;
017import com.ardor3d.renderer.state.TextureState;
018import com.ardor3d.renderer.state.RenderState.StateType;
019import com.ardor3d.scenegraph.Mesh;
020import com.ardor3d.scenegraph.Spatial;
021import com.ardor3d.scenegraph.visitor.Visitor;
022
023public class SceneCompiler {
024
025    public static void compile(final Spatial scene, final Renderer renderer, final CompileOptions options) {
026        // are we making a display list?
027        if (options.isDisplayList()) {
028            // grab our current context
029            final RenderContext context = ContextManager.getCurrentContext();
030
031            // handle camera...
032            // save the current camera...
033            final Camera originalCam = context.getCurrentCamera();
034            // replace with a camera that will always pass frustum checks
035            final Camera yesCam = new Camera(originalCam) {
036                @Override
037                public FrustumIntersect contains(final BoundingVolume bound) {
038                    return FrustumIntersect.Inside;
039                }
040            };
041            context.setCurrentCamera(yesCam);
042
043            // setup for display list...
044            // force all textures to load so their setup calls are not part of the displaylist
045            scene.acceptVisitor(new TextureApplyVisitor(renderer), true);
046            // invalidate any current opengl state information.
047            context.invalidateStates();
048            // generate a DL id by starting our list
049            final int id = renderer.startDisplayList();
050            // push our current buckets to back
051            renderer.getQueue().pushBuckets();
052
053            // render...
054            // render our spatial
055            scene.draw(renderer);
056            // process buckets and then pop them
057            renderer.renderBuckets();
058            renderer.getQueue().popBuckets();
059
060            // end list
061            renderer.endDisplayList();
062
063            // restore old camera
064            context.setCurrentCamera(originalCam);
065
066            // add a display list delegate to the given Spatial
067            scene.setRenderDelegate(new DisplayListDelegate(id, context.getGlContextRep()), context.getGlContextRep());
068        }
069    }
070
071    static class TextureApplyVisitor implements Visitor {
072        private final Renderer _renderer;
073
074        public TextureApplyVisitor(final Renderer renderer) {
075            _renderer = renderer;
076        }
077
078        @Override
079        public void visit(final Spatial spatial) {
080            if (spatial instanceof Mesh) {
081                final Mesh mesh = (Mesh) spatial;
082                final TextureState state = (TextureState) mesh.getWorldRenderState(StateType.Texture);
083                if (state != null) {
084                    _renderer.applyState(state.getType(), state);
085                }
086            }
087        }
088
089    }
090}