Skip to content

Commit

Permalink
New backgrounds (#173)
Browse files Browse the repository at this point in the history
skybox can now be sphere or cube.
  • Loading branch information
i-make-robots authored Oct 13, 2023
2 parents c246946 + 4ae0259 commit 78b74a0
Show file tree
Hide file tree
Showing 10 changed files with 88 additions and 36 deletions.
3 changes: 2 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>com.marginallyclever</groupId>
<artifactId>RobotOverlord</artifactId>
<version>2.9.0</version>
<version>2.10.0</version>
<name>Robot Overlord</name>
<description>A friendly 3D user interface for controlling robots.</description>
<url>http://www.marginallyclever.com/</url>
Expand Down Expand Up @@ -376,6 +376,7 @@
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<version>5.10.0</version>
<scope>test</scope>
</dependency>

Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package com.marginallyclever.robotoverlord.systems.render;
package com.marginallyclever.robotoverlord.components;

import com.jogamp.opengl.GL;
import com.jogamp.opengl.GL3;
import com.marginallyclever.convenience.helpers.MatrixHelper;
import com.marginallyclever.convenience.helpers.OpenGLHelper;
import com.marginallyclever.robotoverlord.components.CameraComponent;
import com.marginallyclever.robotoverlord.components.PoseComponent;
import com.marginallyclever.robotoverlord.parameters.TextureParameter;
import com.marginallyclever.robotoverlord.systems.render.ShaderProgram;
import com.marginallyclever.robotoverlord.systems.render.Viewport;
import com.marginallyclever.robotoverlord.systems.render.mesh.Mesh;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
Expand All @@ -14,11 +15,13 @@
import javax.vecmath.Vector3d;

/**
* A skybox is a cube with 6 textures on it. The camera is inside the cube, looking out.
* A background component is always rendered first and is always behind everything else.
* The transform is always adjusted to the active camera.
* @author Dan Royer
*/
public class SkyBox {
private static final Logger logger = LoggerFactory.getLogger(SkyBox.class);
@ComponentDependency(components = {PoseComponent.class})
public class Background extends Component {
private static final Logger logger = LoggerFactory.getLogger(Background.class);
private transient final TextureParameter textureXPos = new TextureParameter("XPos","/skybox/cube-x-pos.png");
private transient final TextureParameter textureXNeg = new TextureParameter("XNeg","/skybox/cube-x-neg.png");
private transient final TextureParameter textureYPos = new TextureParameter("YPos","/skybox/cube-y-pos.png");
Expand All @@ -28,7 +31,7 @@ public class SkyBox {

private transient final Mesh [] meshes = new Mesh[6];

public SkyBox() {
public Background() {
super();

// build meshes once
Expand Down Expand Up @@ -82,7 +85,7 @@ public SkyBox() {
meshes[5] = mesh5;
}

public void render(GL3 gl,Viewport viewport,ShaderProgram program) {
public void render(GL3 gl, Viewport viewport, ShaderProgram program) {
PoseComponent cameraPose = viewport.getCamera().getEntity().getComponent(PoseComponent.class);

Matrix4d m1 = MatrixHelper.createIdentityMatrix4();
Expand All @@ -101,7 +104,19 @@ public void render(GL3 gl,Viewport viewport,ShaderProgram program) {
program.set1i(gl,"useLighting",0);
program.set1i(gl,"useTexture",1);
program.set1i(gl,"diffuseTexture",0);

program.setVector3d(gl,"cameraPos",new Vector3d(0,0,0)); // Camera position in world space
program.setVector3d(gl,"lightColor",new Vector3d(1,1,1)); // Light color
program.set4f(gl,"objectColor",1,1,1,1);
program.setVector3d(gl,"specularColor",new Vector3d(0.5,0.5,0.5));
program.setVector3d(gl,"ambientLightColor",new Vector3d(0.2,0.2,0.2));

gl.glDepthMask(true);
gl.glColorMask(true,true,true,true);
gl.glStencilMask(0x00);
gl.glStencilFunc(GL.GL_ALWAYS,1,0xFF);
gl.glStencilOp(GL.GL_KEEP,GL.GL_KEEP,GL.GL_REPLACE);
gl.glEnable(GL.GL_TEXTURE_2D);

textureXPos.render(gl); meshes[0].render(gl);
textureXNeg.render(gl); meshes[1].render(gl);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@ public abstract class ComponentFactory {
Decal.class,
Cylinder.class,

Background.class,

OriginAdjustComponent.class,

DHComponent.class,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ public class MaterialComponent extends Component {
public final BooleanParameter isLit = new BooleanParameter("Lit",true);
public final TextureParameter texture = new TextureParameter("Texture",null);
public final BooleanParameter drawOnTop = new BooleanParameter("Draw on top",false);
public final BooleanParameter drawOnBottom = new BooleanParameter("Draw on bottom",false);

public MaterialComponent() {
super();
Expand Down Expand Up @@ -127,6 +128,7 @@ public JSONObject toJSON(SerializationContext context) {
jo.put("shininess",shininess.toJSON(context));
jo.put("texture",texture.toJSON(context));
jo.put("drawOnTop",drawOnTop.toJSON(context));
jo.put("drawOnBottom",drawOnBottom.toJSON(context));
return jo;
}

Expand All @@ -141,6 +143,7 @@ public void parseJSON(JSONObject jo,SerializationContext context) throws JSONExc
shininess.parseJSON(jo.getJSONObject("shininess"),context);
texture.parseJSON(jo.getJSONObject("texture"),context);
if(jo.has("drawOnTop")) drawOnTop.parseJSON(jo.getJSONObject("drawOnTop"),context);
if(jo.has("drawOnBottom")) drawOnBottom.parseJSON(jo.getJSONObject("drawOnBottom"),context);
}

@Override
Expand All @@ -154,6 +157,7 @@ public String toString() {
+ ",shininess=" + shininess.get()
+ ",texture=" + texture.get()
+ ",drawOnTop=" + drawOnTop.get()
+ ",drawOnBottom=" + drawOnBottom.get()
+",\n";
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
* @since 2.7.1
*/
public class MatrixMaterialRenderSet {
// background is always first
public final List<MatrixMaterialRender> onBottom = new ArrayList<>();
public final List<MatrixMaterialRender> opaque = new ArrayList<>();
public final List<MatrixMaterialRender> alpha = new ArrayList<>();
public final List<MatrixMaterialRender> noMaterial = new ArrayList<>();
Expand Down Expand Up @@ -44,6 +46,7 @@ public MatrixMaterialRenderSet(List<Entity> list) {
entity.getComponent(MaterialComponent.class));

if(mmr.materialComponent==null) noMaterial.add(mmr);
else if(mmr.materialComponent.drawOnBottom.get()) onBottom.add(mmr);
else if(mmr.materialComponent.drawOnTop.get()) onTop.add(mmr);
else if(mmr.materialComponent.isAlpha()) alpha.add(mmr);
else opaque.add(mmr);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,6 @@
import com.marginallyclever.robotoverlord.preferences.GraphicsPreferences;
import com.marginallyclever.robotoverlord.systems.render.Compass3D;
import com.marginallyclever.robotoverlord.systems.render.ShaderProgram;
import com.marginallyclever.robotoverlord.systems.render.SkyBox;
import com.marginallyclever.robotoverlord.systems.render.Viewport;
import com.marginallyclever.robotoverlord.systems.render.mesh.Mesh;
import com.marginallyclever.robotoverlord.tools.EditorTool;
Expand Down Expand Up @@ -70,11 +69,6 @@ public class OpenGLRenderPanel implements RenderPanel, GLEventListener, MouseLis
*/
private final Compass3D compass3d = new Compass3D();

/**
* The "very far away" background to the scene.
*/
private final SkyBox skyBox = new SkyBox();

private final List<EditorTool> editorTools = new ArrayList<>();
private int activeToolIndex = -1;

Expand Down Expand Up @@ -458,13 +452,30 @@ private void draw3DScene(GL3 gl) {
gl.glStencilOp(GL3.GL_KEEP, GL3.GL_KEEP, GL3.GL_REPLACE);

viewport.setCamera(camera);
renderLights();
useShaderDefault(gl);
skyBox.render(gl, viewport, shaderDefault);
renderLights();
defaultMaterial.render(gl);
updateBackgrounds();

renderAllEntities(gl, entityManager.getEntities(),shaderDefault);
outlineCollectedEntities(gl);
}

/**
* Position the first background to be on the camera position.
*/
private void updateBackgrounds() {
Background bg = entityManager.getRoot().findFirstComponentRecursive(Background.class);
if(bg==null || !bg.getEnabled()) return;

PoseComponent cameraPose = entityManager.getCamera().getEntity().getComponent(PoseComponent.class);

Matrix4d m1 = MatrixHelper.createIdentityMatrix4();
Vector3d cameraPosition = new Vector3d(cameraPose.getPosition());
m1.setTranslation(cameraPosition);
bg.getEntity().getComponent(PoseComponent.class).setWorld(m1);
}

private void useShaderDefault(GL3 gl) {
Vector3d cameraPos = entityManager.getCamera().getPosition();

Expand Down Expand Up @@ -497,13 +508,11 @@ private void useShaderDefault(GL3 gl) {
}

private void setProjectionMatrix(GL3 gl, ShaderProgram program) {
Matrix4d projectionMatrix = viewport.getChosenProjectionMatrix();
program.setMatrix4d(gl,"projectionMatrix",projectionMatrix);
program.setMatrix4d(gl,"projectionMatrix",viewport.getChosenProjectionMatrix());
}

private void setOrthographicMatrix(GL3 gl3, ShaderProgram program) {
Matrix4d projectionMatrix = viewport.getOrthographicMatrix();
program.setMatrix4d(gl3,"projectionMatrix",projectionMatrix);
program.setMatrix4d(gl3,"projectionMatrix",viewport.getOrthographicMatrix());
}

private void setViewMatrix(GL3 gl3,ShaderProgram program) {
Expand Down Expand Up @@ -553,7 +562,6 @@ private void outlineCollectedEntities(GL3 gl) {

MatrixMaterialRenderSet mmrSet = new MatrixMaterialRenderSet(collectedEntities);
sortMMRAlpha(mmrSet);
useShaderDefault(gl);
drawMMRSetToStencilBuffer(gl,mmrSet);

// only draw where the stencil buffer is not 1 (where there are no collectedEntities)
Expand Down Expand Up @@ -589,6 +597,7 @@ private void drawMMRSetToStencilBuffer(GL3 gl, MatrixMaterialRenderSet mmrSet) {
gl.glStencilFunc(GL.GL_ALWAYS,1,0xFF);
gl.glStencilOp(GL.GL_KEEP,GL.GL_KEEP,GL.GL_REPLACE);

useShaderDefault(gl);
renderMMRSet(gl,mmrSet,shaderDefault);

// resume editing the color buffer, do not change the depth mask.
Expand Down Expand Up @@ -647,14 +656,18 @@ private void renderAllEntities(GL3 gl3,List<Entity> list,ShaderProgram shaderPro
*/
private void renderMMRSet(GL3 gl, MatrixMaterialRenderSet mmrSet, ShaderProgram shaderProgram) {
defaultMaterial.render(gl);
// objects with no material
defaultMaterial.render(gl);
renderMMRList(gl,mmrSet.noMaterial,shaderProgram);
// bottom (background) objects
renderMMRList(gl,mmrSet.onBottom,shaderProgram);
gl.glClear(GL.GL_DEPTH_BUFFER_BIT);

// opaque objects
renderMMRList(gl,mmrSet.opaque,shaderProgram);
// alpha objects
renderMMRList(gl, mmrSet.alpha,shaderProgram);
// objects on top of everything else
// objects with no material
defaultMaterial.render(gl);
renderMMRList(gl,mmrSet.noMaterial,shaderProgram);
// top objects
gl.glDisable(GL3.GL_DEPTH_TEST);
defaultMaterial.render(gl);
renderMMRList(gl,mmrSet.onTop,shaderProgram);
Expand Down Expand Up @@ -727,8 +740,8 @@ private void renderOneMMRItem(GL3 gl, MatrixMaterialRender mmr, ShaderProgram sh
shaderProgram.set1i(gl,"useTexture",useTexture?1:0);

if(useTexture && texture!=null) {
gl.glEnable(GL.GL_TEXTURE_2D);
mmr.materialComponent.render(gl);
shaderProgram.set1f(gl,"useTexture",1);
shaderProgram.set1i(gl,"diffuseTexture",0);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,8 +68,8 @@ public MyTopPanel() {
@Override
public void mouseMoved(MouseEvent e) {
super.mouseMoved(e);
double pan = e.getX() / (double)getWidth();
double tilt = e.getY() / (double)getHeight();
double pan = e.getX() / (double)image.getWidth();
double tilt = e.getY() / (double)image.getHeight();

// repaint the target with a cross-hair based on the SphericalMap.
SphericalMap.CubeCoordinate cube = SphericalMap.planeToCube(pan,tilt);
Expand Down Expand Up @@ -105,14 +105,14 @@ public static void main(String[] args) throws IOException {
public VisuallyTestSphereMap() throws IOException {
setLayout(new BoxLayout(this,BoxLayout.Y_AXIS));

image = ImageIO.read(new File("c:/users/aggra/desktop/whiteRoomSphericalProjection2.png"));
image = ImageIO.read(new File("src/main/resources/skybox/industrial_sunset_02_puresky_4k.png"));
// paint source with image, filling the entire panel.

remapped = new BufferedImage(256*6,256,BufferedImage.TYPE_INT_RGB);
makeMap();

// display a 256 tall and (256*6) wide BufferedImage in the target.
topPanel.setPreferredSize(new Dimension(256*6,512));
topPanel.setPreferredSize(new Dimension(image.getWidth(),image.getHeight()));
bottomPanel.setPreferredSize(new Dimension(256*6,256)); // 1536 = 256*6
add(topPanel);
add(bottomPanel);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,18 +1,19 @@
package com.marginallyclever.robotoverlord.swinginterface.actions;

import com.marginallyclever.robotoverlord.components.*;
import com.marginallyclever.robotoverlord.components.shapes.Sphere;
import com.marginallyclever.robotoverlord.entity.Entity;
import com.marginallyclever.robotoverlord.Project;
import com.marginallyclever.robotoverlord.components.shapes.Box;
import com.marginallyclever.robotoverlord.swinginterface.UnicodeIcon;
import com.marginallyclever.robotoverlord.components.CameraComponent;
import com.marginallyclever.robotoverlord.components.LightComponent;
import com.marginallyclever.robotoverlord.components.PoseComponent;
import com.marginallyclever.robotoverlord.swinginterface.UndoSystem;
import com.marginallyclever.robotoverlord.swinginterface.translator.Translator;

import javax.swing.*;
import javax.vecmath.Matrix4d;
import javax.vecmath.Vector3d;
import java.awt.*;
import java.awt.Component;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;

Expand Down Expand Up @@ -54,14 +55,26 @@ public void clearScene() {
}

public void addDefaultEntities() {
Entity background = new Entity("Background");
background.addComponent(new Background());
project.getEntityManager().addEntityToParent(background, project.getEntityManager().getRoot());
Entity sky = new Entity("Sky");
Sphere skySphere = new Sphere();
sky.addComponent(skySphere);
skySphere.radius.set(-100.0);
MaterialComponent material = sky.getComponent(MaterialComponent.class);
material.texture.set("/skybox/industrial_sunset_02_puresky_4k.tga");
material.setLit(false);
project.getEntityManager().addEntityToParent(sky, background);
sky.getComponent(PoseComponent.class).setRotation(new Vector3d(90,0,0));

Entity mainCamera = new Entity("Main Camera");
CameraComponent camera = new CameraComponent();
mainCamera.addComponent(camera);
PoseComponent pose = mainCamera.getComponent(PoseComponent.class);

project.getEntityManager().addEntityToParent(mainCamera, project.getEntityManager().getRoot());
pose.setPosition(new Vector3d(25,20,15));
camera.lookAt(new Vector3d(0,0,0));
project.getEntityManager().addEntityToParent(mainCamera, project.getEntityManager().getRoot());

Entity light0 = new Entity("Light");
light0.addComponent(pose = new PoseComponent());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ public void decorateMaterial(ViewPanelFactory view, Component component) {
view.add(material.specular);
view.addRange(material.shininess, 128, 0);
view.add(material.drawOnTop);
view.add(material.drawOnBottom);

view.addFilename(material.texture, TextureParameter.getFilters());
}
Expand Down
Binary file not shown.

0 comments on commit 78b74a0

Please sign in to comment.