/** * Copyright (c) 2003-2009, Xith3D Project Group all rights reserved. * * Portions based on the Java3D interface, Copyright by Sun Microsystems. * Many thanks to the developers of Java3D and Sun Microsystems for their * innovation and design. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are met: * * Redistributions of source code must retain the above copyright notice, * this list of conditions and the following disclaimer. * * Redistributions in binary form must reproduce the above copyright notice, * this list of conditions and the following disclaimer in the documentation * and/or other materials provided with the distribution. * * Neither the name of the 'Xith3D Project Group' nor the names of its * contributors may be used to endorse or promote products derived from this * software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) A * RISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE * POSSIBILITY OF SUCH DAMAGE */ package org.xith3d.render.preprocessing; import org.xith3d.render.OpenGLCapabilities; import org.xith3d.render.states.StateUnit; import org.xith3d.render.states.units.ColoringStateUnit; import org.xith3d.render.states.units.LineAttribsStateUnit; import org.xith3d.render.states.units.MaterialStateUnit; import org.xith3d.render.states.units.PointAttribsStateUnit; import org.xith3d.render.states.units.PolygonAttribsStateUnit; import org.xith3d.render.states.units.RenderingAttribsStateUnit; import org.xith3d.render.states.units.ShaderProgramStateUnit; import org.xith3d.render.states.units.TextureUnitStateUnit; import org.xith3d.scenegraph.Appearance; import org.xith3d.scenegraph.ColoringAttributes; import org.xith3d.scenegraph.RenderingAttributes; import org.xith3d.scenegraph.Shape3D; import org.xith3d.scenegraph.TexCoordGeneration; import org.xith3d.scenegraph.Texture; import org.xith3d.scenegraph.TextureAttributes; import org.xith3d.scenegraph.TextureUnit; import org.xith3d.scenegraph.TransparencyAttributes; import org.xith3d.scenegraph._SG_PrivilegedAccess; /** * Atom for rendering a single Shape3D along with its geometry arrays. * * @author David Yazel * @author Marvin Froehlich (aka Qudus) * @author Florian Hofmann (aka Goliat) GLSL Shader support */ public class ShapeAtom extends ShadowAtom { public static final int STATE_TYPE = 0; public static final Appearance DEFAULT_APPEARANCE = new Appearance(); private static RenderingAttributes transparentRenderAttribs = null; private final StateUnit[] stateUnitCache = new StateUnit[ StateUnit.MAX_STATE_TYPES ]; private int numValidTUs = 0; public int lastComputedPolysCount = 0; /** * * @param shape * @param glCaps */ public ShapeAtom( Shape3D shape, OpenGLCapabilities glCaps ) { super( ShapeAtom.STATE_TYPE, shape ); // make sure view state shaders are first // now set all the materials Appearance a = shape.getAppearance(); if ( a == null ) a = DEFAULT_APPEARANCE; updateStateUnit( MaterialStateUnit.makeMaterialStateUnit( a.getMaterial(), stateUnitCache ) ); getStateUnit( MaterialStateUnit.STATE_TYPE ).updateCachedStateId(); updateStateUnit( PolygonAttribsStateUnit.makePolygonAttribsStateUnit( a.getPolygonAttributes(), stateUnitCache ) ); getStateUnit( PolygonAttribsStateUnit.STATE_TYPE ).updateCachedStateId(); updateStateUnit( LineAttribsStateUnit.makeLineAttribsStateUnit( a.getLineAttributes(), stateUnitCache ) ); getStateUnit( LineAttribsStateUnit.STATE_TYPE ).updateCachedStateId(); updateStateUnit( PointAttribsStateUnit.makePointAttribsStateUnit( a.getPointAttributes(), stateUnitCache ) ); getStateUnit( PointAttribsStateUnit.STATE_TYPE ).updateCachedStateId(); updateStateUnit( ColoringStateUnit.makeColoringStateUnit( a.getColoringAttributes(), a.getTransparencyAttributes(), stateUnitCache ) ); getStateUnit( ColoringStateUnit.STATE_TYPE ).updateCachedStateId(); if ( ( a.getRenderingAttributes() == null ) && ( a.getTransparencyAttributes() != null ) ) { if ( transparentRenderAttribs == null ) { transparentRenderAttribs = new RenderingAttributes( true, true, 0.0f, RenderingAttributes.GREATER ); } updateStateUnit( RenderingAttribsStateUnit.makeRenderingStateUnit( transparentRenderAttribs, stateUnitCache ) ); } else { updateStateUnit( RenderingAttribsStateUnit.makeRenderingStateUnit( a.getRenderingAttributes(), stateUnitCache ) ); } getStateUnit( RenderingAttribsStateUnit.STATE_TYPE ).updateCachedStateId(); updateStateUnit( ShaderProgramStateUnit.makeShaderProgramStateUnit( a.getShaderProgramContext(), stateUnitCache ) ); getStateUnit( ShaderProgramStateUnit.STATE_TYPE ).updateCachedStateId(); this.numValidTUs = a.getTextureUnitsCount(); for ( int i = 0; i < numValidTUs; i++ ) { updateStateUnit( TextureUnitStateUnit.makeTextureUnitStateUnit( i, a.getTextureUnit( i ), stateUnitCache ) ); getStateUnit( TextureUnitStateUnit.STATE_TYPES[ i ] ).updateCachedStateId(); } for ( int i = numValidTUs; i < TextureUnitStateUnit.DEFAULT_UNIT.length; i++ ) { updateStateUnit( TextureUnitStateUnit.DEFAULT_UNIT[ i ] ); getStateUnit( TextureUnitStateUnit.STATE_TYPES[ i ] ).updateCachedStateId(); } } /** * * @param app * @param glCaps */ public void updateStateUnits( Appearance app, OpenGLCapabilities glCaps ) { // This is already checked before the call to the method now! /* if ( app.isStatic() && !_SG_PrivilegedAccess.isStaticDirty( app ) ) { return; } */ updateLightsAndFogs(); // check and update Material Shader final MaterialStateUnit materialShader = (MaterialStateUnit)getStateUnit( MaterialStateUnit.STATE_TYPE ); if ( materialShader.isDefault() ) { if ( app.getMaterial() != null ) { updateStateUnit( MaterialStateUnit.makeMaterialStateUnit( app.getMaterial(), stateUnitCache ) ); _SG_PrivilegedAccess.setChanged( app.getMaterial(), false ); } } else if ( app.getMaterial() == null ) { updateStateUnit( MaterialStateUnit.makeMaterialStateUnit( null, null ) ); } else if ( app.getMaterial().isChanged() ) { materialShader.update( app.getMaterial() ); updateStateMap( materialShader ); _SG_PrivilegedAccess.setChanged( app.getMaterial(), false ); } getStateUnit( MaterialStateUnit.STATE_TYPE ).updateCachedStateId(); // check and update PolygonAttributes Shader final PolygonAttribsStateUnit polygonAttrShader = (PolygonAttribsStateUnit)getStateUnit( PolygonAttribsStateUnit.STATE_TYPE ); if ( polygonAttrShader.isDefault() ) { if ( app.getPolygonAttributes() != null ) { updateStateUnit( PolygonAttribsStateUnit.makePolygonAttribsStateUnit( app.getPolygonAttributes(), stateUnitCache ) ); _SG_PrivilegedAccess.setChanged( app.getPolygonAttributes(), false ); } } else if ( app.getPolygonAttributes() == null ) { updateStateUnit( PolygonAttribsStateUnit.makePolygonAttribsStateUnit( null, null ) ); } else if ( app.getPolygonAttributes().isChanged() ) { polygonAttrShader.update( app.getPolygonAttributes() ); updateStateMap( polygonAttrShader ); _SG_PrivilegedAccess.setChanged( app.getPolygonAttributes(), false ); } getStateUnit( PolygonAttribsStateUnit.STATE_TYPE ).updateCachedStateId(); // check and update LineAttributes Shader final LineAttribsStateUnit lineAttrShader = (LineAttribsStateUnit)getStateUnit( LineAttribsStateUnit.STATE_TYPE ); if ( lineAttrShader.isDefault() ) { if ( app.getLineAttributes() != null ) { updateStateUnit( LineAttribsStateUnit.makeLineAttribsStateUnit( app.getLineAttributes(), stateUnitCache ) ); _SG_PrivilegedAccess.setChanged( app.getLineAttributes(), false ); } } else if ( app.getLineAttributes() == null ) { updateStateUnit( LineAttribsStateUnit.makeLineAttribsStateUnit( null, null ) ); } else if ( app.getLineAttributes().isChanged() ) { lineAttrShader.update( app.getLineAttributes() ); updateStateMap( lineAttrShader ); _SG_PrivilegedAccess.setChanged( app.getLineAttributes(), false ); } getStateUnit( LineAttribsStateUnit.STATE_TYPE ).updateCachedStateId(); // check and update LineAttributes Shader final PointAttribsStateUnit pointAttrShader = (PointAttribsStateUnit)getStateUnit( PointAttribsStateUnit.STATE_TYPE ); if ( pointAttrShader.isDefault() ) { if ( app.getPointAttributes() != null ) { updateStateUnit( PointAttribsStateUnit.makePointAttribsStateUnit( app.getPointAttributes(), stateUnitCache ) ); _SG_PrivilegedAccess.setChanged( app.getPointAttributes(), false ); } } else if ( app.getPointAttributes() == null ) { updateStateUnit( PointAttribsStateUnit.makePointAttribsStateUnit( null, null ) ); } else if ( app.getPointAttributes().isChanged() ) { pointAttrShader.update( app.getPointAttributes() ); updateStateMap( pointAttrShader ); _SG_PrivilegedAccess.setChanged( app.getPointAttributes(), false ); } getStateUnit( PointAttribsStateUnit.STATE_TYPE ).updateCachedStateId(); // check and update ColoringAttributes Shader final ColoringStateUnit colorShader = (ColoringStateUnit)getStateUnit( ColoringStateUnit.STATE_TYPE ); //if ( colorShader.isDefault() ) if ( ColoringStateUnit.isDefault( colorShader ) ) { if ( ( app.getColoringAttributes() != null ) || ( app.getTransparencyAttributes() != null ) ) { updateStateUnit( ColoringStateUnit.makeColoringStateUnit( app.getColoringAttributes(), app.getTransparencyAttributes(), stateUnitCache ) ); if ( app.getColoringAttributes() != null ) _SG_PrivilegedAccess.setChanged( app.getColoringAttributes(), false ); if ( app.getTransparencyAttributes() != null ) _SG_PrivilegedAccess.setChanged( app.getTransparencyAttributes(), false ); } } else if ( ( app.getColoringAttributes() == null ) && ( app.getTransparencyAttributes() == null ) ) { updateStateUnit( ColoringStateUnit.makeColoringStateUnit( app.getColoringAttributes(), app.getTransparencyAttributes(), stateUnitCache ) ); } else { final ColoringAttributes colorAttribs = app.getColoringAttributes(); final boolean c1 = ( colorAttribs == null ); final boolean c2 = ( colorShader.getColoringAttributes() == ColoringStateUnit.DEFAULT_COLOR_ATTR ); final boolean c; if ( c1 ) { if ( !c2 ) c = true; else c = false; } else if ( colorAttribs.isChanged() ) c = true; else c = false; final TransparencyAttributes transAttribs = app.getTransparencyAttributes(); final boolean t1 = ( transAttribs == null ); final boolean t2 = ( colorShader.getTransparencyAttributes() == ColoringStateUnit.DEFAULT_TRANS_ATTR ); final boolean t; if ( t1 ) { if ( !t2 ) t = true; else t = false; } else if ( transAttribs.isChanged() ) t = true; else t = false; if ( c || t ) { colorShader.update( app.getColoringAttributes(), app.getTransparencyAttributes() ); updateStateMap( colorShader ); if ( !c1 ) _SG_PrivilegedAccess.setChanged( app.getColoringAttributes(), false ); if ( !t1 ) _SG_PrivilegedAccess.setChanged( app.getTransparencyAttributes(), false ); } } getStateUnit( ColoringStateUnit.STATE_TYPE ).updateCachedStateId(); // check and update RenderingAttributes Shader final RenderingAttribsStateUnit renderingAttrShader = (RenderingAttribsStateUnit)getStateUnit( RenderingAttribsStateUnit.STATE_TYPE ); if ( renderingAttrShader.isDefault() ) { if ( app.getRenderingAttributes() != null ) { updateStateUnit( RenderingAttribsStateUnit.makeRenderingStateUnit( app.getRenderingAttributes(), stateUnitCache ) ); _SG_PrivilegedAccess.setChanged( app.getRenderingAttributes(), false ); } } else if ( app.getRenderingAttributes() == null ) { updateStateUnit( RenderingAttribsStateUnit.makeRenderingStateUnit( null, null ) ); } else if ( app.getRenderingAttributes().isChanged() ) { renderingAttrShader.update( app.getRenderingAttributes() ); updateStateMap( renderingAttrShader ); _SG_PrivilegedAccess.setChanged( app.getRenderingAttributes(), false ); } getStateUnit( RenderingAttribsStateUnit.STATE_TYPE ).updateCachedStateId(); final ShaderProgramStateUnit shaderProgramStateUnit = (ShaderProgramStateUnit)getStateUnit( ShaderProgramStateUnit.STATE_TYPE ); if ( shaderProgramStateUnit.isDefault() ) { if ( app.getShaderProgramContext() != null ) { updateStateUnit( ShaderProgramStateUnit.makeShaderProgramStateUnit( app.getShaderProgramContext(), stateUnitCache ) ); _SG_PrivilegedAccess.setChanged( app.getShaderProgramContext(), false ); } } else if ( app.getShaderProgramContext() == null ) { updateStateUnit( ShaderProgramStateUnit.makeShaderProgramStateUnit( null, null ) ); } else if ( app.getShaderProgramContext().isChanged() ) { shaderProgramStateUnit.update( app.getShaderProgramContext() ); updateStateMap( shaderProgramStateUnit ); _SG_PrivilegedAccess.setChanged( app.getShaderProgramContext(), false ); } getStateUnit( ShaderProgramStateUnit.STATE_TYPE ).updateCachedStateId(); // check and update Texture Shader final int tuc = app.getTextureUnitsCount(); for ( int i = 0; i < tuc; i++ ) { final TextureUnitStateUnit texShader = (TextureUnitStateUnit)getStateUnit( TextureUnitStateUnit.STATE_TYPES[ i ] ); final TextureUnit tu = app.getTextureUnit( i ); final Texture texture = ( tu == null ) ? null : tu.getTexture(); final TextureAttributes texAttribs = ( tu == null ) ? null : tu.getTextureAttributes(); final TexCoordGeneration texCoordGen = ( tu == null ) ? null : tu.getTexCoordGeneration(); if ( texShader.isDefault() ) { if ( ( texture != null ) || ( texAttribs != null ) || ( texCoordGen != null ) ) { updateStateUnit( TextureUnitStateUnit.makeTextureUnitStateUnit( i, tu, stateUnitCache ) ); //texture.setChanged( false ); } } else if ( ( tu == null ) || ( ( texture == null ) && ( texAttribs == null ) && ( texCoordGen == null ) ) ) { updateStateUnit( TextureUnitStateUnit.makeTextureUnitStateUnit( i, null, null ) ); } else if ( ( texture != null && texture.isChanged() ) || ( texAttribs != null && texAttribs.isChanged() ) || ( texCoordGen != null && texCoordGen.isChanged() ) ) { texShader.update( texture, texAttribs, texCoordGen ); updateStateMap( texShader ); //texture.setChanged( false ); } getStateUnit( TextureUnitStateUnit.STATE_TYPES[ i ] ).updateCachedStateId(); } if ( tuc < numValidTUs ) { for ( int i = tuc; i < numValidTUs; i++ ) { updateStateUnit( TextureUnitStateUnit.DEFAULT_UNIT[ i ] ); updateStateMap( TextureUnitStateUnit.DEFAULT_UNIT[ i ] ); getStateUnit( TextureUnitStateUnit.STATE_TYPES[ i ] ).updateCachedStateId(); } } numValidTUs = tuc; if ( app.isStatic() ) { _SG_PrivilegedAccess.markStaticClean( app ); } } @Override public boolean isTranslucent() { return ( translucent ); } }