addShadowVolumes(volumeNode, light); volumeNode.updateGeometricState(0, false);
addShadowVolumes(light); volumeNode.updateWorldVectors();
   public void doRender(Renderer r) {       // init states       init();              if (!renderShadows) {           renderScene(r);           if (renderVolume) {               getShadowLights();               setupOccluderMeshes();               generateVolumes();               drawVolumes(r);           }           return;       }       // grab the shadowcasting lights       getShadowLights();       // grab the occluders       setupOccluderMeshes();       // if no occluders or no shadow casting lights, just render the scene normally and return.       if (occluderMeshes.size() == 0 || shadowLights.size() == 0) {           //render normal           renderScene(r);           cleanup();           return;       } else {           // otherwise render an ambient pass by masking the diffuse and specular of shadowcasting lights.           if (lightingMethod == ADDITIVE) {               maskShadowLights(LightState.MASK_DIFFUSE | LightState.MASK_SPECULAR);               saveEnforcedStates();               Renderer.enforceState(noTexture);               renderScene(r);               replaceEnforcedStates();               unmaskShadowLights();               r.setPolygonOffset(0.0f, -5.0f);           } else {               renderScene(r);           }       }       generateVolumes();       for (int l = shadowLights.size(); --l >= 0; ) {           Light light = shadowLights.get(l);           light.setEnabled(false);       }       for (int l = shadowLights.size(); --l >= 0; ) {           Light light = shadowLights.get(l);           // Clear out the stencil buffer           r.clearStencilBuffer();           light.setEnabled(true);           saveEnforcedStates();           Renderer.enforceState(noTexture);           Renderer.enforceState(forTesting);           Renderer.enforceState(colorDisabled);           Renderer.enforceState(stencilFrontFaces);           Renderer.enforceState(cullBackFace);           volumeNode.detachAllChildren();           addShadowVolumes(volumeNode, light);           volumeNode.updateGeometricState(0, false);           volumeNode.onDraw(r);           Renderer.enforceState(stencilBackFaces);           Renderer.enforceState(cullFrontFace);           volumeNode.onDraw(r);           Renderer.enforceState(colorEnabled);           Renderer.enforceState(forColorPassTesting);           Renderer.enforceState(cullBackFace);           if (lightingMethod == ADDITIVE) {               Renderer.enforceState(lights);               Renderer.enforceState(blended);               lights.detachAll();               lights.attach(light);               Renderer.enforceState(stencilDrawWhenNotSet);               renderScene(r);           } else {               if (rTexture) {                   Renderer.enforceState(modblended);                   Renderer.enforceState(zbufferAlways);                   Renderer.enforceState(cullBackFace);                   Renderer.enforceState(noLights);                   Renderer.enforceState(stencilDrawOnlyWhenSet);                       shadowColor.a = 1 - light.getAmbient().a;                   shadowQuad.setDefaultColor(shadowColor);                   r.setOrtho();                   resetShadowQuad(r);                   shadowQuad.draw(r);                   r.unsetOrtho();               }           }           light.setEnabled(false);           replaceEnforcedStates();       }       for (int l = shadowLights.size(); --l >= 0; ) {           Light light = (Light)shadowLights.get(l);           light.setEnabled(true);       }       if (lightingMethod == ADDITIVE && rTexture ) {           saveEnforcedStates();           Renderer.enforceState(noStencil);           Renderer.enforceState(colorEnabled);           Renderer.enforceState(cullBackFace);           Renderer.enforceState(blendTex);           renderScene(r);           replaceEnforcedStates();       }       if (renderVolume) {           drawVolumes(r);       }       cleanup();   }