@Override public Runnable getRenderRunnable() { return () -> { ensureSceneThread(); if (sceneState.views.isEmpty()) return; renderer.submit(() -> sceneState.create(renderer)); }; }
// TODO: there's a lot of room for optimization here: don't rebuild // lists that haven't changed etc.... for now we just don't care... IRenderState create(IRenderer renderer) { // 1. add meshes and mesh updates to render state final List<IRenderUpdate> updates = new ArrayList<>(); if (rebuildMeshes) { renderables = new ArrayList<>(); materials.clear(); geometries.clear(); meshes.forEach( (mesh, state) -> { materials.add(mesh.getMaterial()); geometries.add(mesh.getGeometry()); }); } meshes.forEach( (mesh, state) -> { IMaterial material = mesh.getMaterial(); IGeometry geometry = mesh.getGeometry(); boolean materialChanged; boolean geometryChanged; if (state.renderable == null) { // TODO: optionally we could do the first update() on // drawable already here, using a shared context. state.renderable = renderer.createRenderable(mesh); materialChanged = true; geometryChanged = true; } else { materialChanged = material.getUpdater().test(); geometryChanged = geometry.getUpdater().test() || mesh.getUpdater().testAndClear(); } if (materialChanged || geometryChanged) { updates.add( new RenderUpdate(state.renderable, mesh, materialChanged, geometryChanged)); } if (rebuildMeshes) renderables.add(state.renderable); }); // second loop required to clear view flags materials.forEach(material -> material.getUpdater().clear()); geometries.forEach(geometry -> geometry.getUpdater().clear()); // seal collections final List<Renderable> renderRenderables = Collections.unmodifiableList(renderables); final List<IRenderUpdate> renderUpdates = Collections.unmodifiableList(updates); // 2. add lights to render state // currently updates are not checked, we simply update everything final List<ILight> renderLights = Collections.unmodifiableList(new ArrayList<>(lights)); // 3. set view matrices for each updated camera, add to render state final List<IRenderTargetState> targets = new ArrayList<>(); views.forEach( (view, svs) -> { if (svs.camera.getUpdater().test()) svs.viewCameraState = new ViewCameraState(view, svs.camera); targets.add( new IRenderTargetState() { @Override public IView getView() { return view; } @Override public IViewCameraState getViewCameraState() { return svs.viewCameraState; } @Override public List<Renderable> getRenderables() { return renderRenderables; } @Override public List<ILight> getLights() { return renderLights; } }); }); // second loop required to clear view flags views.forEach((view, svs) -> svs.camera.getUpdater().clear()); // seal collections final List<IRenderTargetState> renderTargets = Collections.unmodifiableList(targets); // 4. hey, we're done! rebuildMeshes = false; return new IRenderState() { @Override public List<IRenderUpdate> getRenderUpdates() { return renderUpdates; } @Override public List<IRenderTargetState> getRenderStates() { return renderTargets; } }; }