Using java3d, how can I colorize not on a per vertex base but on a per face base?
I try to learn about java3d but what Shape3d I did produce does not look as expected.
I want to colorize different triangles in different colors, but I don't see how to do it.
Texture looks like an overkill, and what's more, I haven't mastered this part at all.
As far as I've seen Materials work on a complete GeometryArray, so are no good here.
Per vertex colors won't do the trick.
I fond the solution. "per vertex colors" really are per vertex reference, so each vertex can have a different color for each of its faces.
Here is a working example (regrettably not very small):
package examples;
import javax.media.j3d.Alpha;
import javax.media.j3d.AmbientLight;
import javax.media.j3d.Appearance;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.Bounds;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.GeometryArray;
import javax.media.j3d.IndexedTriangleArray;
import javax.media.j3d.Node;
import javax.media.j3d.PolygonAttributes;
import javax.media.j3d.RotationInterpolator;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.media.j3d.View;
import javax.media.j3d.ViewPlatform;
import javax.vecmath.Color3f;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3f;
import com.sun.j3d.utils.geometry.GeometryInfo;
import com.sun.j3d.utils.geometry.NormalGenerator;
import com.sun.j3d.utils.universe.MultiTransformGroup;
import com.sun.j3d.utils.universe.SimpleUniverse;
import com.sun.j3d.utils.universe.ViewingPlatform;
public class Example {
public static void main(final String[] args) {
new Example();
}
public Example() {
final SimpleUniverse universe = new SimpleUniverse();
final BranchGroup group = new BranchGroup();
final TransformGroup tg = new TransformGroup();
final BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0);
final Node blob = createMonster();
{ //to enable rotation
tg.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
tg.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
}
// Create rotation to see all sides of the object
final Transform3D btrans = new Transform3D();
btrans.rotX(1);
final Transform3D ztrans = new Transform3D();
ztrans.rotZ(-1);
btrans.mul(ztrans);
final RotationInterpolator ri = createRotation(tg, bounds, btrans, 7000);
tg.addChild(ri);
tg.addChild(blob);
//
group.addChild(tg);
//
addLight(group, new Color3f(1f, 1f, 0f), new Vector3f(4.0f, +7.0f, -12.0f));
addLight(group, new Color3f(1f, 1f, 1f));
//
final ViewingPlatform viewingPlatform = universe.getViewingPlatform();
final ViewPlatform view = viewingPlatform.getViewPlatform();
view.setViewAttachPolicy(View.NOMINAL_SCREEN);
viewingPlatform.setNominalViewingTransform();
final MultiTransformGroup mtg = viewingPlatform.getMultiTransformGroup();
final TransformGroup vtg = mtg.getTransformGroup(0);
final Transform3D t1 = btrans;
vtg.getTransform(t1);
t1.setScale(2);
vtg.setTransform(t1);
group.compile();
// add the group of objects to the Universe
universe.addBranchGraph(group);
}
private Node createMonster() {
final Shape3D child = createShape();
final Appearance fillAppNode = new Appearance();
final PolygonAttributes pAtt = new PolygonAttributes();
// avoid trouble with clockwise faces
pAtt.setCullFace(PolygonAttributes.CULL_NONE);
pAtt.setBackFaceNormalFlip(true);
fillAppNode.setPolygonAttributes(pAtt);
child.setAppearance(fillAppNode);
return child;
}
private Shape3D createShape() {
final Point3d[] points = new Point3d[] {//
new Point3d(-1, 1, 0), //
new Point3d(1, 1, 0), //
new Point3d(1, -1, 0), //
new Point3d(-1, -1, 0), //
new Point3d(0, 0, 1), //
};
final int[] idxs = new int[] {// the triangle faces
0, 1, 2,//
2, 3, 0,//
1, 0, 4,//
1, 2, 4,//
2, 3, 4,//
3, 0, 4 };
final IndexedTriangleArray ita = new IndexedTriangleArray(points.length, GeometryArray.COORDINATES
| GeometryArray.COLOR_3, idxs.length);
ita.setCoordinates(0, points);
ita.setCoordinateIndices(0, idxs);
//per vertex colors really are per vertex reference
//so each vertex can have a different color for each of its faces
final Color3f[] colors = new Color3f[] {//
new Color3f(1, 0, 1),//
new Color3f(0, 1, 0),//
new Color3f(0, 0, 1),//
new Color3f(1, 1, 0),//
new Color3f(1, 1, 1),//
};
ita.setColors(0, colors);
ita.setColorIndices(0, idxs);
ita.setColorIndices(0, new int[] { 0, 0, 0, 1, 1, 1 });
//
final GeometryInfo gi = new GeometryInfo(ita);
//also generate normal vectors so that the surface can be light
final NormalGenerator normalGenerator = new NormalGenerator();
normalGenerator.generateNormals(gi);
final GeometryArray geometryArray = gi.getGeometryArray();
return new Shape3D(geometryArray);
}
private RotationInterpolator createRotation(final TransformGroup objScale, final Bounds bounds,
final Transform3D btrans, final long milis) {
final Alpha alpha = new Alpha(-1, Alpha.INCREASING_ENABLE, 0, 0, milis, 0, 0, 0, 0, 0);
final RotationInterpolator ri = new RotationInterpolator(alpha, objScale, btrans, 0.0f, (float) Math.PI * 2.0f);
ri.setSchedulingBounds(bounds);
return ri;
}
private void addLight(final BranchGroup group, final Color3f light1Color, final Vector3f ligthDirection) {
{
final BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0);
final DirectionalLight light1 = new DirectionalLight(light1Color, ligthDirection);
light1.setInfluencingBounds(bounds);
group.addChild(light1);
}
}
private void addLight(final BranchGroup group, final Color3f light1Color) {
{
final BoundingSphere bounds = new BoundingSphere(new Point3d(0.0, 0.0, 0.0), 100.0);
final AmbientLight light1 = new AmbientLight(light1Color);
light1.setInfluencingBounds(bounds);
group.addChild(light1);
}
}
}
You will have to draw each face separately, assigning a color to each. For example:
Appearance polygon1Appearance = new Appearance();
// set your color here
QuadArray polygon1 = new QuadArray (4, QuadArray.COORDINATES);
polygon1.setCoordinate(0, new Point3f (0f, 0f, 0f));
polygon1.setCoordinate(1, new Point3f (2f, 0f, 0f));
polygon1.setCoordinate(2, new Point3f (2f, 3f, 0f));
polygon1.setCoordinate(3, new Point3f (0f, 3f, 0f));
objRoot.addChild(new Shape3D(polygon1, polygon1Appearance));
Related
I am trying to draw a 2d sprite into a 3d environment to try and get a delver style game. Since this is for a project I am using just LibGDX and no game engines. If anyone knows any good guide or at least point me in the right direction, anything is appreciated.
Luckily, Delvers source code is publicly available to review so you can see how Delver did it. I believe they did use Decals, possibly extending more functionality to them. Decal is definitely what you are looking for.
Here are a few samples from the Decals wiki on LibGDX
Instantiate:
Decal decal = Decal.newDecal(textureRegion, true);
Look at Camera (so its always facing it)
decal.lookAt(camera.position, camera.up);
DecalBatch is used to render the decal.
Check out the LibGDX wiki on Decals for a full breakdown.
Full example from LibGDX tests:
import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.FPSLogger;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.PerspectiveCamera;
import com.badlogic.gdx.graphics.Texture;
import com.badlogic.gdx.graphics.g2d.TextureRegion;
import com.badlogic.gdx.graphics.g3d.decals.CameraGroupStrategy;
import com.badlogic.gdx.graphics.g3d.decals.Decal;
import com.badlogic.gdx.graphics.g3d.decals.DecalBatch;
import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.tests.utils.GdxTest;
import com.badlogic.gdx.tests.utils.PerspectiveCamController;
import com.badlogic.gdx.utils.Array;
public class SimpleDecalTest extends GdxTest {
private static final int NUM_DECALS = 3;
DecalBatch batch;
Array<Decal> decals = new Array<Decal>();
PerspectiveCamera camera;
PerspectiveCamController controller;
FPSLogger logger = new FPSLogger();
public void create () {
float width = Gdx.graphics.getWidth();
float height = Gdx.graphics.getHeight();
camera = new PerspectiveCamera(45, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
camera.near = 1;
camera.far = 300;
camera.position.set(0, 0, 5);
controller = new PerspectiveCamController(camera);
Gdx.input.setInputProcessor(controller);
batch = new DecalBatch(new CameraGroupStrategy(camera));
TextureRegion[] textures = {new TextureRegion(new Texture(Gdx.files.internal("data/egg.png"))),
new TextureRegion(new Texture(Gdx.files.internal("data/wheel.png"))),
new TextureRegion(new Texture(Gdx.files.internal("data/badlogic.jpg")))};
Decal decal = Decal.newDecal(1, 1, textures[1]);
decal.setPosition(0, 0, 0);
decals.add(decal);
decal = Decal.newDecal(1, 1, textures[0], true);
decal.setPosition(0.5f, 0.5f, 1);
decals.add(decal);
decal = Decal.newDecal(1, 1, textures[0], true);
decal.setPosition(1, 1, -1);
decals.add(decal);
decal = Decal.newDecal(1, 1, textures[2]);
decal.setPosition(1.5f, 1.5f, -2);
decals.add(decal);
decal = Decal.newDecal(1, 1, textures[1]);
decal.setPosition(2, 2, -1.5f);
decals.add(decal);
}
Vector3 dir = new Vector3();
private boolean billboard = true;
public void render () {
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
Gdx.gl.glEnable(GL20.GL_DEPTH_TEST);
camera.update();
for (int i = 0; i < decals.size; i++) {
Decal decal = decals.get(i);
if (billboard) {
// billboarding for ortho cam :)
// dir.set(-camera.direction.x, -camera.direction.y, -camera.direction.z);
// decal.setRotation(dir, Vector3.Y);
// billboarding for perspective cam
decal.lookAt(camera.position, camera.up);
}
batch.add(decal);
}
batch.flush();
logger.log();
}
#Override
public void dispose () {
batch.dispose();
}
}
Also, Delvers source code if interested: https://github.com/Interrupt/delverengine
I am currently having issues with trying to render two textures onto two totally separate objects through a single vertex, and fragment shader. The issue seems to lie in trying to index, and bind the two textures onto their own objects. In trying to index and bind the textures, the smaller index will always appear onto both objects.
Can someone help me, or at least push me into the right direction?
here is my code for the main class, the renderer, and the fragment shader.
(feel free to request more code)
main:
import Engine.IO.Image;
import Engine.IO.Input;
import Engine.IO.Window;
import Engine.graphics.*;
import Engine.maths.Vector2f;
import Engine.maths.Vector3f;
import Engine.objects.Camera;
import Engine.objects.GameObject;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.opengl.GL13;
public class Main implements Runnable {
public Thread game;
public Window window;
public Renderer renderer;
public Shader shader;
public final int WIDTH = 1280, HEIGHT = 720;
private String[] textureImageNames = {"nice_dude.jpg", "color.jpg", "pepe.jpg"};
public GameObject thing1 = new GameObject(new Vector3f(-1, 0, 0), new Vector3f(0, 0, 0), new Vector3f(1, 1, 1), new Mesh(new Vertex[]{
new Vertex(new Vector3f(-0.5f, 0.5f, 0.0f), new Vector3f(0.0f, 0.0f, 1.0f), new Vector2f(0.0f,0.0f)),
new Vertex(new Vector3f(0.5f, 0.5f, 0.0f), new Vector3f(0.0f, 0.0f, 1.0f), new Vector2f(1.0f,0.0f)),
new Vertex(new Vector3f(0.5f, -0.5f, 0.0f), new Vector3f(0.0f, 0.0f, 1.0f), new Vector2f(1.0f,1.0f)),
new Vertex(new Vector3f(-0.5f, -0.5f, 0.0f), new Vector3f(0.0f, 0.0f, 1.0f), new Vector2f(0.0f,1.0f))
}, new int[]{
0, 1, 2, 0, 3, 2
}), new Material(textureImageNames[0]));
public GameObject thing2 = new GameObject(new Vector3f(1, 0, 0), new Vector3f(0, 0, 0), new Vector3f(1, 1, 1), new Mesh(new Vertex[]{
new Vertex(new Vector3f(-0.5f, 0.5f, 0.0f), new Vector3f(0.0f, 0.0f, 1.0f), new Vector2f(0.0f,0.0f)),
new Vertex(new Vector3f(0.5f, 0.5f, 0.0f), new Vector3f(0.0f, 0.0f, 1.0f), new Vector2f(1.0f,0.0f)),
new Vertex(new Vector3f(0.5f, -0.5f, 0.0f), new Vector3f(0.0f, 0.0f, 1.0f), new Vector2f(1.0f,1.0f)),
new Vertex(new Vector3f(-0.5f, -0.5f, 0.0f), new Vector3f(0.0f, 0.0f, 1.0f), new Vector2f(0.0f,1.0f))
}, new int[]{
0, 1, 2, 0, 3, 2
}), new Material(textureImageNames[2]));
public Camera camera = new Camera(new Vector3f(0, 0, 1), new Vector3f(0, 0,0));
public void start(){
game = new Thread(this,"game");
game.start();
}
public void init(){
System.out.println("Initializing Game!");
window = new Window(WIDTH, HEIGHT, "Game");
shader = new Shader("/shaders/mainVertex.glsl", "/shaders/mainFragment.glsl");
window.setBackgroundColor(0.0f, 0.5f, 0.0f);
window.create();
thing1.getMesh().create();
thing2.getMesh().create();
thing1.getMaterial().create(new Image());
thing2.getMaterial().create(new Image());
shader.create();
renderer = new Renderer(window, shader);
renderer.renderMesh();
renderer.enableShaderProgram();
renderer.bindVAO(thing1);
renderer.bindVAO(thing2);
renderer.setUniformIndex(thing1,"tex", GL13.GL_TEXTURE0);
renderer.setUniformIndex(thing2,"tex2", GL13.GL_TEXTURE1);
}
public void run(){
init();
while(!window.shouldClose() && !Input.isKeyDown(GLFW.GLFW_KEY_ESCAPE)){
update();
render();
if(Input.isKeyDown(GLFW.GLFW_KEY_F11)){window.setFullscreen(!window.isFullscreen());}
}
close();
}
private void update(){
//System.out.println("updating Game!");
window.update();
camera.update();
}
private void render(){
renderer.updateRenderer(thing1);
renderer.updateRenderer(thing2);
renderer.renderCamera(camera);
window.swapBuffers();
}
private void close(){
window.destroy();
thing1.getMesh().destroy();
thing1.destroyMaterial();
thing2.getMesh().destroy();
thing2.destroyMaterial();
shader.destroy();
renderer.destroyRenderer();
}
public static void main(String[] args){
new Main().start();
}
}
render class:
package Engine.graphics;
import Engine.IO.Window;
import Engine.maths.Matrix4f;
import Engine.objects.Camera;
import Engine.objects.GameObject;
import org.lwjgl.opengl.*;
public class Renderer {
private Shader shader;
private Window window;
public Renderer(Window window, Shader shader){
this.shader = shader;
this.window = window;
}
public void renderMesh() {
GL30.glEnableVertexAttribArray(0);
GL30.glEnableVertexAttribArray(1);
GL30.glEnableVertexAttribArray(2);
}
public void enableShaderProgram(){
shader.bind();
}
public void bindVAO(GameObject object){
GL30.glBindVertexArray(object.getMesh().getVAO());
}
public void setUniformIndex(GameObject object, String textureName, int index){
GL13.glActiveTexture(index);
shader.setUniform(textureName, index);
GL13.glBindTexture(GL11.GL_TEXTURE_2D, object.getMaterial().getTextureID());
}
public void updateRenderer(GameObject object){
GL11.glDrawElements(GL11.GL_TRIANGLES, object.getMesh().getIndices().length, GL11.GL_UNSIGNED_INT, 0);
shader.setUniform("model", Matrix4f.transform(object.getPosition(), object.getRotation(), object.getScale()));
shader.setUniform("projection", window.getProjectionMatrix());
}
public void renderCamera(Camera camera){
shader.setUniform("view", Matrix4f.view(camera.getPosition(), camera.getRotation()));
}
public void destroyRenderer(){
shader.unBind();
GL15.glBindBuffer(GL15.GL_ELEMENT_ARRAY_BUFFER, 0);
GL30.glDisableVertexAttribArray(0);
GL30.glDisableVertexAttribArray(1);
GL30.glDisableVertexAttribArray(2);
GL30.glBindVertexArray(0);
}
}
fragment shader:
#version 460 core
in vec3 passColor;
in vec2 passTextureCoord;
out vec4 outColor;
uniform sampler2D tex;
uniform sampler2D tex2;
void main(){
outColor = texture(tex, passTextureCoord);
outColor = texture(tex2, passTextureCoord);
}
The value which has to be set to the texture sampler uniform is the index of the texture unit rather then the texture unit constant (e.g.: 0 for GL13.GL_TEXTURE0 and 1 for GL13.GL_TEXTURE1):
public void setUniformIndex(GameObject object, String textureName, int unit, int index){
shader.setUniform(textureName, index);
GL13.glActiveTexture(unit);
GL13.glBindTexture(GL11.GL_TEXTURE_2D, object.getMaterial().getTextureID());
}
OpenGL is a state engine. Binding a VAO and or a texture object changes a global state. It is not possible to bind 2 objects at once. Only the last object which was bound is stated. You have to bind the Vertex Array Object and the texture object before the draw call:
private void render(){
renderer.bindVAO(thing1);
renderer.setUniformIndex(thing1,"tex", GL13.GL_TEXTURE0, 0);
renderer.updateRenderer(thing1);
renderer.bindVAO(thing2);
renderer.setUniformIndex(thing2,"tex2", GL13.GL_TEXTURE1, 1);
renderer.updateRenderer(thing2);
renderer.renderCamera(camera);
window.swapBuffers();
}
My rigid body models are dropping through the floor. I am experimenting with Libgdx. When models fall on the ground created from a box they stop moving, but when I replace the ground with a model created from blender the objects fall through. I am trying to build a road track. Here is the code and other examples I tried I keep getting objects that fall through the modeled ground. I'm using blender for the modelling.
public BulletSample(ThrustCopter thrustCopter) {
super(thrustCopter);
// Create ModelBatch that will render all models using a camera
modelBatch = new ModelBatch(new DefaultShaderProvider());
// Create a camera and point it to our model
camera = new PerspectiveCamera(70, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
camera.position.set(10f, 10f, 12f);
camera.lookAt(0, 0, 0);
camera.near = 0.1f;
camera.far = 300f;
camera.update();
// Create the generic camera input controller to make the app interactive
cameraController = new CameraInputController(camera);
Gdx.input.setInputProcessor(cameraController);
// Set up environment with simple lighting
environment = new Environment();
environment.set(new ColorAttribute(ColorAttribute.AmbientLight, 0.4f, 0.4f, 0.4f, 1f));
// environment.set(new ColorAttribute(ColorAttribute.Fog, 0.13f, 0.13f, 0.13f, 1f));
environment.add(new DirectionalLight().set(0.8f, 0.8f, 0.8f, -0.8f, 0.3f, -1f));
shadowLight = new DirectionalShadowLight(1024, 1024, 60, 60, 1f, 300);
shadowLight.set(0.8f, 0.8f, 0.8f, -1f, -.8f, -.2f);
environment.add(shadowLight);
environment.shadowMap = shadowLight;
shadowBatch = new ModelBatch(new DepthShaderProvider());
Bullet.init();
collisionConfiguration = new btDefaultCollisionConfiguration();
dispatcher = new btCollisionDispatcher(collisionConfiguration);
broadphase = new btDbvtBroadphase();
solver = new btSequentialImpulseConstraintSolver();
world = new btDiscreteDynamicsWorld(dispatcher, broadphase, solver, collisionConfiguration);
world.setGravity(new Vector3(0, -9.81f, 1f));
ModelBuilder modelBuilder = new ModelBuilder();
/* Model ground = modelBuilder.createBox(40f, 2f, 40f,
new Material(ColorAttribute.createDiffuse(Color.GREEN)),
Usage.Position | Usage.Normal);
groundInstance=new ModelInstance(ground);
btCollisionShape groundshape = new btBoxShape(new Vector3(20, 1f, 20));
shapes.add(groundshape);
btRigidBody body = new btRigidBody(0,null,groundshape);
bodies.add(body);
world.addRigidBody(body); */
// testing rigid body ground with model from blender
game.manager.load("gameAssets/roadtest1.g3db", Model.class);
game.manager.finishLoading();
Model roadmodel = game.manager.get("gameAssets/roadtest1.g3db", Model.class);
roadInstance = new ModelInstance(roadmodel);
//instances.add(road);
btCollisionShape roadshape = createConvexHullShape(roadmodel, true);
shapes.add(roadshape);
btRigidBody body = new btRigidBody(0, null, roadshape);
world.addRigidBody(body);
Vector3 position=new Vector3();
for(int i=0;i<10;i++){
Model box = modelBuilder.createBox(1f, 1f, 1f,
new Material(ColorAttribute.createDiffuse(Color.BLUE)),
Usage.Position | Usage.Normal);
ModelInstance boxInstance=new ModelInstance(box);
instances.add(boxInstance);
models.add(box);
if(i<5){
position.set(-1, i+1, 0);
}else{
position.set(1, i-4, 0);
}
boxInstance.transform.setToTranslation(position);
btDefaultMotionState motionState = new btDefaultMotionState(boxInstance.transform);
motionState.setWorldTransform(boxInstance.transform.trn(0, 0, 0));
motionStates.add(motionState);
btCollisionShape boxshape = new btBoxShape(new Vector3(0.5f, 0.5f, 0.5f));
shapes.add(boxshape);
btRigidBody boxbody = new btRigidBody(1, motionState, boxshape);
bodies.add(boxbody);
world.addRigidBody(boxbody);
}
//Loading model
game.manager.load("planeanim1.g3db", Model.class);
game.manager.finishLoading();
Model model = game.manager.get("planeanim1.g3db", Model.class);
ModelInstance plane = new ModelInstance(model);
instances.add(plane);
plane.transform.setToRotation(Vector3.Y, 180);
plane.transform.trn(0, 7, 10);
btDefaultMotionState motionState = new btDefaultMotionState(plane.transform);
motionState.setWorldTransform(plane.transform.trn(0, 0, 0));
// motionState.setWorldTransform(plane.transform.rotate(0, 0, .5f,45));
motionStates.add(motionState);
btCollisionShape planeshape = createConvexHullShape(model,true);
shapes.add(planeshape);
btRigidBody planebody = new btRigidBody(5, motionState, planeshape);
bodies.add(planebody);
world.addRigidBody(planebody);
planebody.userData="plane";
planebody.applyCentralImpulse(new Vector3(0,0,-65));
// You use an AnimationController to control animations. Each control is tied to the model instance
controller = new AnimationController(plane);
// Pick the current animation by name
controller.setAnimation("Scene",-1);
contactListener = new MyContactListener();
}
public static btConvexHullShape createConvexHullShape (final Model model, boolean optimize) {
final Mesh mesh = model.meshes.get(0);
final btConvexHullShape shape = new btConvexHullShape(mesh.getVerticesBuffer(), mesh.getNumVertices(), mesh.getVertexSize());
if (!optimize) return shape;
// now optimize the shape
final btShapeHull hull = new btShapeHull(shape);
hull.buildHull(shape.getMargin());
final btConvexHullShape result = new btConvexHullShape(hull);
// delete the temporary shape
shape.dispose();
hull.dispose();
return result;
}
#Override
public void dispose() {
groundInstance.model.dispose();
instances.clear();
modelBatch.dispose();
for (Model model : models)
model.dispose();
for (btRigidBody body : bodies) {
body.dispose();
}
for (btMotionState motion : motionStates)
motion.dispose();
for (btCollisionShape shape : shapes)
shape.dispose();
world.dispose();
collisionConfiguration.dispose();
dispatcher.dispose();
broadphase.dispose();
solver.dispose();
contactListener.dispose();
shadowBatch.dispose();
shadowLight.dispose();
}
#Override
public void render(float delta) {
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
Gdx.gl.glClearColor(0.13f, 0.13f, 0.13f, 1);
if(started){
world.stepSimulation(Gdx.graphics.getDeltaTime(), 5);
for (int i = 0; i < motionStates.size; i++) {
motionStates.get(i).getWorldTransform(instances.get(i).transform);
}
}else{
if(Gdx.input.isTouched()){
started=true;
System.out.println(instances.size);
if(Gdx.input.justTouched())instances.get(10).transform.rotate(0,0.2f,0,25);
}
}
// Respond to user events and update the camera
cameraController.update();
controller.update(delta);
shadowLight.begin(Vector3.Zero, camera.direction);
shadowBatch.begin(shadowLight.getCamera());
shadowBatch.render(instances);
shadowBatch.end();
shadowLight.end();
// Draw all model instances using the camera
modelBatch.begin(camera);
//modelBatch.render(groundInstance, environment);
modelBatch.render(roadInstance, environment);
modelBatch.render(instances, environment);
modelBatch.end();
super.render(delta);
}
I need to make a rubik cube in JavaFX not using the standard libs and SceneBulider. The question is - I have a texture that I need to wrap around the cube. Using this:
Skinning custom 3D cube in javafx 8
and this Create a cube using different textures in JavaFX
was not able to get any result.
Anyway here's my Controller.
import com.sun.javafx.geom.transform.GeneralTransform3D;
import javafx.fxml.FXML;
import javafx.scene.*;
import javafx.scene.image.Image;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import javafx.scene.paint.Color;
import javafx.scene.paint.PhongMaterial;
import javafx.scene.shape.Box;
import javafx.scene.shape.DrawMode;
import javafx.scene.shape.MeshView;
import javafx.scene.shape.TriangleMesh;
import javafx.scene.transform.Rotate;
import javafx.scene.transform.Translate;
public class Controller{
/* double mousePosX;
double mousePosY;
double mouseOldX;
double mouseOldY;
Rotate rotateX = new Rotate(30, 0, 0, 0, Rotate.X_AXIS);
Rotate rotateY = new Rotate(20, 0, 0, 0, Rotate.Y_AXIS);*/
#FXML
Camera camera = new PerspectiveCamera(true);
#FXML
private Box rubik;
#FXML
private AnchorPane anchor;
#FXML
private MeshView mesh;
#FXML
private AmbientLight ambientlight;
private void paintCube()
{
Image dieImage = new Image(getClass().getResourceAsStream("textura.png"));
PhongMaterial material = new PhongMaterial();
material.setDiffuseMap(dieImage);
ambientlight.setColor(Color.WHITE);
float hw = 300/2f;
float hh = 300/2f;
float hd = 300/2f;
float points[] =
{
0, 0, 300, //P0
300, 0, 300, //P1
0, 300, 300, //P2
300, 300, 300, //P3
0, 0, 0, //P4
300, 0, 0, //P5
0, 300, 0, //P6
300, 300, 0 //P7
};
float tex[] =
{
0.25f, 0, //T0
0.5f, 0, //T1
0, 0.25f, //T2
0.25f, 0.25f, //T3
0.5f, 0.25f, //T4
0.75f, 0.25f, //T5
1, 0.25f, //T6
0, 0.5f, //T7
0.25f, 0.5f, //T8
0.5f, 0.5f, //T9
0.75f, 0.5f, //T10
1, 0.5f, //T11
0.25f, 0.75f, //T12
0.5f, 0.75f //T13
};
int faces[] =
{
5,1,4,0,0,3 //P5,T1 ,P4,T0 ,P0,T3
,5,1,0,3,1,4 //P5,T1 ,P0,T3 ,P1,T4
,0,3,4,2,6,7 //P0,T3 ,P4,T2 ,P6,T7
,0,3,6,7,2,8 //P0,T3 ,P6,T7 ,P2,T8
,1,4,0,3,2,8 //P1,T4 ,P0,T3 ,P2,T8
,1,4,2,8,3,9 //P1,T4 ,P2,T8 ,P3,T9
,5,5,1,4,3,9 //P5,T5 ,P1,T4 ,P3,T9
,5,5,3,9,7,10 //P5,T5 ,P3,T9 ,P7,T10
,4,6,5,5,7,10 //P4,T6 ,P5,T5 ,P7,T10
,4,6,7,10,6,11 //P4,T6 ,P7,T10 ,P6,T11
,3,9,2,8,6,12 //P3,T9 ,P2,T8 ,P6,T12
,3,9,6,12,7,13 //P3,T9 ,P6,T12 ,P7,T13
};
TriangleMesh mesh1 = new TriangleMesh();
mesh1.getPoints().addAll(points);
mesh1.getTexCoords().addAll(tex);
mesh1.getFaces().addAll(faces);
//mesh = new MeshView(mesh1);
//mesh.setMaterial(material);
mesh.setMesh(mesh1);
rubik.setMaterial(material);
}
#FXML
public void initialize()
{
Rotate cameraRotateX, cameraRotateY, cameraRotateZ;
Translate cameraTranslate;
cameraRotateX = new Rotate(10, Rotate.X_AXIS);
cameraRotateY = new Rotate(10, Rotate.Y_AXIS);
cameraRotateZ = new Rotate(0, Rotate.Z_AXIS);
rubik.getTransforms().addAll(
cameraRotateX,
cameraRotateY,
cameraRotateZ);
// Rotate rotateX = new Rotate(30, 0, 0, 0, Rotate.X_AXIS);
// Rotate rotateY = new Rotate(20, 0, 0, 0, Rotate.Y_AXIS);
//rubik.setRotate(45);
paintCube();
}
/* #FXML
public void klik(MouseEvent mouseEvent) {
mouseOldX = mouseEvent.getX();
mouseOldY = mouseEvent.getY();
}
#FXML
public void gowno(MouseEvent mouseEvent) {
mousePosX = mouseEvent.getX();
mousePosY = mouseEvent.getY();
rotateX.setAngle(rotateX.getAngle()-(mousePosY - mouseOldY));
rotateY.setAngle(rotateY.getAngle()+(mousePosX - mouseOldX));
mouseOldX = mousePosX;
mouseOldY = mousePosY;
}
*/
}
the cube is 300/300/300.
hello guys i would be very thankful for help with my code. i just made a main menu for my first game in Java3d (VirtualUniverse). So my problem that i cant solve is that i trying to mapping an texture on the plane that i made and its not work. the texture not appear it just coloring the plane with the texture pixels but nothing more. im trying to load the image in line 78 of the backGround class... i have here 3 classe 1) backGround is the main class that renders all. 2)plane class here i make a plane. 3) Menutexts class here i made the words.
1) backGround class:
package Aplication;
import com.sun.j3d.utils.universe.SimpleUniverse;
import java.applet.Applet;
import java.awt.BorderLayout;
import java.awt.Frame;
import java.awt.GraphicsConfiguration;
import javax.media.j3d.AmbientLight;
import javax.media.j3d.Appearance;
import javax.media.j3d.Background;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.BranchGroup;
import javax.media.j3d.Canvas3D;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.ImageComponent2D;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Texture;
import javax.media.j3d.TextureAttributes;
import javax.media.j3d.TransformGroup;
import javax.vecmath.Point3d;
import javax.vecmath.Vector3f;
import com.sun.j3d.utils.applet.MainFrame;
import com.sun.j3d.utils.image.TextureLoader;
import com.sun.j3d.utils.universe.SimpleUniverse;
public class backGround extends Applet{
private java.net.URL bgImage = null;
public backGround(){
init();
setLayout(new BorderLayout());
GraphicsConfiguration config =
SimpleUniverse.getPreferredConfiguration();
Canvas3D c = new Canvas3D(config);
add("Center", c);
SimpleUniverse u = new SimpleUniverse(c);
//set background Texture
u.addBranchGraph( createBackground() );
BranchGroup scene = createSceneGraphMenu();
// This will move the ViewPlatform back a bit so the
// objects in the scene can be viewed.
u.getViewingPlatform().setNominalViewingTransform();
scene.compile();
u.addBranchGraph(scene);
}
public void init(){
setSize(1280,650);
}
// create the BackGround
public BranchGroup createBackground(){
BranchGroup bg = new BranchGroup();
ImageComponent2D image = new TextureLoader(
"C:/Users/bounty_wiz/workspace/finalProject/images/sky.jpg", this).getScaledImage( 1300,750 );
Background background = new Background(image);
background.setApplicationBounds(new BoundingSphere(new Point3d(0,0,0), 1000));
bg.addChild(background);
return bg;
}
// create the main menu
public BranchGroup createSceneGraphMenu(){
BranchGroup menu = new BranchGroup();
// Load Texture
Texture tex = new TextureLoader( "C:/Users/bounty_wiz/workspace/finalProject/images/grass.jpg", this ).getTexture( );
Appearance appear = new Appearance(); // appearance to configure the texture
Shape3D planee = new plane(appear).getShape(); // create plane ( constructor of plane class)
appear.setTexture(tex);
planee.setBounds(new BoundingSphere());
menu.addChild(planee);
// set ambient light
AmbientLight lightA = new AmbientLight();
lightA.setInfluencingBounds(new BoundingSphere());
menu.addChild(lightA);
//set Directional light
DirectionalLight lightD1 = new DirectionalLight();
lightD1.setInfluencingBounds(new BoundingSphere());
Vector3f direction = new Vector3f(-1.0f, -1.0f, -1.0f);
direction.normalize();
lightD1.setDirection(direction);
menu.addChild(lightD1);
// make texts
TransformGroup trans = new Menutexts().getTrans();
menu.addChild(trans);
return menu;
}
public static void main(String argv[]) {
Frame frame = new MainFrame(new backGround(), 750, 750);
}
}
/* ==== 2) plane class =============================*/
package Aplication;
import java.awt.Frame;
import javax.media.j3d.Appearance;
import javax.media.j3d.Geometry;
import javax.media.j3d.GeometryArray;
import javax.media.j3d.Material;
import javax.media.j3d.QuadArray;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Texture;
import javax.vecmath.Color3f;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;
import com.sun.j3d.utils.image.TextureLoader;
public class plane extends Shape3D {
private Shape3D plane = new Shape3D();
public plane(Appearance app){
plane.setGeometry(createGeometry(new Point3f(-1.5f, -0.5f, -5.0f), new Point3f(-1.5f, -0.5f, 1.0f),new Point3f(1.5f, -0.5f, 1.0f), new Point3f(1.5f, -0.5f, -5.0f)));
plane.setAppearance(createAppearance(app));
}
private Geometry createGeometry(Point3f A, Point3f B, Point3f C, Point3f D){
QuadArray plane = new QuadArray(4, GeometryArray.COORDINATES
| GeometryArray.NORMALS);
plane.setCoordinate(0, A);
plane.setCoordinate(1, B);
plane.setCoordinate(2, C);
plane.setCoordinate(3, D);
Vector3f a = new Vector3f(A.x - B.x, A.y - B.y, A.z - B.z);
Vector3f b = new Vector3f(C.x - B.x, C.y - B.y, C.z - B.z);
Vector3f n = new Vector3f();
n.cross(b, a);
n.normalize();
plane.setNormal(0, n);
plane.setNormal(1, n);
plane.setNormal(2, n);
plane.setNormal(3, n);
return plane;
}
private Appearance createAppearance(Appearance app){
Color3f color = new Color3f(0.0f,1.5f,0.0f);
Material material = new Material();
material.setDiffuseColor(color);
app.setMaterial(material);
return app;
}
public Shape3D getShape(){
return plane;
}
}
/======= 3) Menutexts class ============================/
package Aplication;
import java.awt.Color;
import java.awt.Font;
import javax.media.j3d.AmbientLight;
import javax.media.j3d.Appearance;
import javax.media.j3d.BoundingSphere;
import javax.media.j3d.DirectionalLight;
import javax.media.j3d.Font3D;
import javax.media.j3d.FontExtrusion;
import javax.media.j3d.Material;
import javax.media.j3d.Shape3D;
import javax.media.j3d.Text3D;
import javax.media.j3d.Transform3D;
import javax.media.j3d.TransformGroup;
import javax.vecmath.Color3f;
import javax.vecmath.Point3f;
import javax.vecmath.Vector3f;
public class Menutexts {
private String fontName = "TestFont";
private String singlePlayer = null;
private String multiPlayer = null;
private String instructions = null;
TransformGroup objScale;
public Menutexts(){
singlePlayer = "Single Player";
multiPlayer = "MultiPlayer";
instructions = "Instructions";
objScale = new TransformGroup();
Transform3D t3d = new Transform3D();
// Assuming uniform size chars, set scale to fit string in view
t3d.setScale(1.5/16);
objScale.setTransform(t3d);
// identity. Enable the TRANSFORM_WRITE capability so that
// our behavior code can modify it at runtime. Add it to the
// root of the subgraph.
TransformGroup objTrans = new TransformGroup();
objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_WRITE);
objTrans.setCapability(TransformGroup.ALLOW_TRANSFORM_READ);
objScale.addChild(objTrans);
Font3D f3d;
f3d = new Font3D(new Font(fontName, Font.ITALIC, 1),
new FontExtrusion());
Text3D txt1 = new Text3D(f3d, singlePlayer, new Point3f( -2.2f, 1f, -1.f));
Text3D txt2 = new Text3D(f3d, multiPlayer, new Point3f( -2.2f, -0.3f, -1.f));
Text3D txt3 = new Text3D(f3d, instructions, new Point3f( -2.2f, -1.4f, -1.f));
Shape3D shape1 = new Shape3D();
Shape3D shape2 = new Shape3D();
Shape3D shape3 = new Shape3D();
Appearance app = new Appearance();
Material shapeMaterial = new Material();
shapeMaterial.setLightingEnable(true);
shapeMaterial.setDiffuseColor(new Color3f(1,1,0));
app.setMaterial(shapeMaterial);
shape1.setGeometry(txt1);
shape1.setAppearance(app);
shape2.setGeometry(txt2);
shape2.setAppearance(app);
shape3.setGeometry(txt3);
shape3.setAppearance(app);
// set Lightning
Color3f ambientColor = new Color3f(1.0f, 1.0f, 0.0f);
AmbientLight ambientLightNode = new AmbientLight(ambientColor);
ambientLightNode.setInfluencingBounds(new BoundingSphere());
objTrans.addChild(ambientLightNode);
// Set up the directional lights
Color3f light1Color = new Color3f(0.862f, 0.862f, 0.862f);
Vector3f light1Direction = new Vector3f(-1.0f, -1.0f, -1.0f);
DirectionalLight light1
= new DirectionalLight(light1Color, light1Direction);
light1.setInfluencingBounds(new BoundingSphere());
objTrans.addChild(light1);
objTrans.addChild(shape1);
objTrans.addChild(shape2);
objTrans.addChild(shape3);
}
public TransformGroup getTrans(){
return objScale;
}
}