Jmonkey engine 3.0 Drawing points - java

How can I draw a 3D-point (or point sprite) in 3D space?
There is no documentation for drawing a point in JMonkey Engine site or anywhere else. Just a single point. Then updating the coordinates. No color, just a dot in 3D space.

A point (as opposed to a sphere) can be created using a mesh in which you directly set its buffers (or technically buffer; since a points mesh doesn't require an index buffer as other more complex meshes require. See How can I draw a straight line in the JMonkey Engine library). Mesh creation is documented here.
An example of creating points in 3D space using a mesh is below:
import com.jme3.app.SimpleApplication;
import com.jme3.material.Material;
import com.jme3.math.*;
import com.jme3.renderer.RenderManager;
import com.jme3.scene.*;
import com.jme3.util.BufferUtils;
public class Main extends SimpleApplication {
public static void main(String[] args) {
Main app = new Main();
app.start();
}
#Override
public void simpleInitApp() {
Vector3f[] lineVerticies=new Vector3f[5];
lineVerticies[0]=new Vector3f(2,0,0);
lineVerticies[1]=new Vector3f(-1,0,1);
lineVerticies[2]=new Vector3f(0,1,1);
lineVerticies[3]=new Vector3f(1,1,1);
lineVerticies[4]=new Vector3f(1,4,0);
plotPoints(lineVerticies,ColorRGBA.White);
}
public void plotPoints(Vector3f[] lineVerticies, ColorRGBA pointColor){
Mesh mesh = new Mesh();
mesh.setMode(Mesh.Mode.Points);
mesh.setBuffer(VertexBuffer.Type.Position, 3, BufferUtils.createFloatBuffer(lineVerticies));
mesh.updateBound();
mesh.updateCounts();
Geometry geo=new Geometry("line",mesh);
Material mat = new Material(assetManager, "Common/MatDefs/Misc/Unshaded.j3md");
mat.setColor("Color", pointColor);
geo.setMaterial(mat);
rootNode.attachChild(geo);
}
#Override
public void simpleUpdate(float tpf) {
//TODO: add update code
}
#Override
public void simpleRender(RenderManager rm) {
//TODO: add render code
}
}
This will create the points within pointVerticies as shown below
Later if you need to update infomation in a buffer you can do so using:
VertexBuffer posBuffer = mesh.getBuffer(Type.Position);
posBuffer.updateData(BufferUtils.createFloatBuffer(newData));
posBuffer.setUpdateNeeded();
mesh.updateCounts();
mesh.updateBound();
Or (much more efficiently) you can just attach your geometry to a node and move that (depending on your usage case).
Notes
In its most basic state the Vertex buffer expects x1,y1,z1,x2,y2,z2,x3.... etc with no demarcation between where one vertex ends and the other begins. So the following would enter 3 vertices into the buffer; (1.1,1.2,1.3), (2.1,2.2,2.3) and (3.1,3.2,3.3)
m.setBuffer(VertexBuffer.Type.Position, 3, new float[]{1.1,1.2,1.3,2.1,2.2,2.3,3.1,3.2,3.3});
However the createFloatBuffer() method converts from an array of Vector3f into this form.
Also; its often possible to 'get away with' not calling mesh.updateBound();, however without it objects may be culled because the graphics card believes them to be off screen when actually they are visible

Related

Setting image instead of java standard ellipse Java Processing

I'm trying to create a solar system using processing but I'm stuck at trying to set an image instead of using the java standard elipse image.
I started this at school and it consisted of an ellipse rotating around another ellipse.
package processing;
import processing.core.PApplet;
import processing.core.PImage;
public class SolarSystem extends PApplet{
PImage background;
Pianets earth;
public void settings() {
size(650,500);
}
public void setup() {
background = loadImage("C:\\background\\bg.jpg");
earth = new Pianets(this, width/2,height/2,40, 200, 0);
}
public void draw() {
background(background);
earth.showEarth();
earth.rotateEarth(0.007f);
}
public static void main(String[] args) {
PApplet.main("processing.SolarSystem");
}
}
Planets class
package processing;
import processing.core.PApplet;
public class Pianets {
PApplet vis;
float x0,y0; //centre
float diam;
float r; //distance from the centre
float alpha; //rotation angle
public Pianeti(PApplet applet, float x, float y, float diam,float r, float alpha){
vis = applet;
this.x0=x;
this.y0=y;
this.diam=diam;
this.r=r;
this.alpha=alpha;
}
void rotateEarth(float deltaAlpha){
alpha +=deltaAlpha;
}
void showEarth(){
//drawing the body of object at the centre
vis.ellipse(x0, y0, diam, diam);
float x = x0 + r*vis.cos(alpha);
float y = y0 + r*vis.sin(alpha);
vis.ellipse(x,y,diam,diam);
}
I created two images on paint that are the earth and the sun but I don't know how to set the image up.
Questions like this are best answered by looking at the Processing reference. There's an Image section that lists a loadImage() function for loading an image file, and an image() function for drawing it. Please read those.
You should also get into the habit of breaking your problem down into smaller pieces. For example, instead of posting your whole project (which has nothing to do with loading images right now), try to create a smaller example program that just shows a single image. Get that working perfectly before moving on. Then if you're confused about something, you can post a MCVE along with a specific technical question.
Shameless self-promotion: I wrote a tutorial on images in Processing available here.

How can I render a LibGDX modelInstance on Vuforia AR library?

I know most questions on the community should be done with at least some code. But I´m totally lost here, I don´t even know where to start. What I want to do is use the Vuforia AR Library to render LibGDX 3D modelInstances. However, I don't know how can I make Vuforia render the modelInstances or use a libGDX camera as it´s camera.
I've done external research but I have not been able to find useful information. Is there anyone who can help me get started with this?
Please note that I am not versed in Vuforia AR specifically, but the question has gone unanswered for a while, so I will give it a shot.
The Camera in LibGDX is essentially just a wrapper for two 4x4 matrices, the view matrix Camera#view, and the projection matrix Camer#projection (there is another Matrix, the model matrix, used for world space transformations, however I believe [but am not 100% certain] that in LibGDX, this matrix is already incorporated into the view matrix [so Camera#view is actually the model-view matrix]).
Anyway, following on from this, unless there is a simpler solution that I am not aware of, you should be able to use these underlying matrices to deal with projections between the the Vuforia and LibGDX apis.
(recommended further reading: Model, View, Projection matrices in 3D graphics)
Next is rendering LibGDX 3D ModelInstances using Vuforia. A general solution to this problem, would be to convert the ModelInstance into something that Vuforia can recognize. This would be done by taking the mesh/vertex data represented by the LibGDX model, and feeding it directly into Vuforia.
IMO, the best way of going about this, would be to use a a core representation of the model data which can easily be given to both Vuforia and LibGDX (for example, a certain file format that both can recognize, or as raw FloatBuffers which should be easy to wrap up and give to either API). For reference, LibGDX stores models as vertex information in a collection of FloatBuffers, accessible through Model#meshes or ModelInstance#model#meshes.
Ok. So I finfally managed to combine both libraries. I´m not sure if what I´m doing is the most efficient way of working but it has worked for me.
First of all I´m basing myself on the Sample Apps from Vuforia. Specifically using the FrameMarkers example.
I opened an empty LibGDX project, imported the Vuforia jar and copied the SampleApplicationControl, SampleApplicationException, SampleApplicationGLView, SampleApplicationSession, FrameMarkerRenderer and FrameMarker.
Next, I created some attributes on the AndroidLauncher class of LibGDX and initialized all the Vuforia Stuff:
public class AndroidLauncher extends AndroidApplication implements SampleApplicationControl{
private static final String LOGTAG = "FrameMarkers";
// Our OpenGL view:
public SampleApplicationGLView mGlView;
public SampleApplicationSession vuforiaAppSession;
// Our renderer:
public FrameMarkerRenderer mRenderer;
MyGDX gdxRender;
// The textures we will use for rendering:
public Vector<Texture> mTextures;
public RelativeLayout mUILayout;
public Marker dataSet[];
public GestureDetector mGestureDetector;
public LoadingDialogHandler loadingDialogHandler = new LoadingDialogHandler(
this);
// Alert Dialog used to display SDK errors
private AlertDialog mErrorDialog;
boolean mIsDroidDevice = false;
#Override
protected void onCreate (Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
vuforiaAppSession = new SampleApplicationSession(this);
vuforiaAppSession.setmActivity(this);
AndroidApplicationConfiguration config = new AndroidApplicationConfiguration();
// Load any sample specific textures:
mTextures = new Vector<Texture>();
loadTextures();
startLoadingAnimation();
vuforiaAppSession.initAR(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
gdxRender = new MyGDX (vuforiaAppSession);
gdxRender.setTextures(mTextures);
initialize(gdxRender, config);
mGestureDetector = new GestureDetector(this, new GestureListener());
mIsDroidDevice = android.os.Build.MODEL.toLowerCase().startsWith(
"droid");
}
I needed to set the activity so I created the setmActivity() on the SampleApplicationSession.
After that I implemented the Libgdx ApplicationAdapter class and passed the vuforiaAppSession as an attribute to access all the stuff I initialized.
public class MyGDX extends ApplicationAdapter {
ModelInstance modelInstanceHouse;
private AnimationController controller;
Matrix4 lastTransformCube;
// Constants:
static private float kLetterScale = 25.0f;
static private float kLetterTranslate = 25.0f;
// OpenGL ES 2.0 specific:
private static final String LOGTAG = "FrameMarkerRenderer";
private int shaderProgramID = 0;
private Vector<com.mygdx.robot.Texture> mTextures;
//SampleApplicationSession vuforiaAppSession;
PerspectiveCamera cam;
ModelBuilder modelBuilder;
Model model;
ModelInstance instance;
ModelBatch modelBatch;
static boolean render;
public SampleApplicationSession vuforiaAppSession;
public MyGDX ( SampleApplicationSession vuforiaAppSession){
super();
this.vuforiaAppSession = vuforiaAppSession;
}
The last important thing to keep in mind is the render() method. I based myself on the the render method of the FrameMarkerRenderer. It has a boolean that gets activated when the camera starts. So I simple changed the variable both on the vuforia AR initialization and the render() method. I had to put the camera on and identity matrix and multiply the model by the modelViewMatrix.
#Override
public void render() {
if (render) {
// Clear color and depth buffer
GLES20.glClear(GLES20.GL_COLOR_BUFFER_BIT | GLES20.GL_DEPTH_BUFFER_BIT);
// Get the state from Vuforia and mark the beginning of a rendering
// section
State state = Renderer.getInstance().begin();
// Explicitly render the Video Background
Renderer.getInstance().drawVideoBackground();
GLES20.glEnable(GLES20.GL_DEPTH_TEST);
// We must detect if background reflection is active and adjust the
// culling direction.
// If the reflection is active, this means the post matrix has been
// reflected as well,
// therefore standard counter clockwise face culling will result in
// "inside out" models.
GLES20.glEnable(GLES20.GL_CULL_FACE);
GLES20.glCullFace(GLES20.GL_BACK);
cam.update();
modelBatch.begin(cam);
if (Renderer.getInstance().getVideoBackgroundConfig().getReflection() == VIDEO_BACKGROUND_REFLECTION.VIDEO_BACKGROUND_REFLECTION_ON)
GLES20.glFrontFace(GLES20.GL_CW); // Front camera
else
GLES20.glFrontFace(GLES20.GL_CCW); // Back camera
// Set the viewport
int[] viewport = vuforiaAppSession.getViewport();
GLES20.glViewport(viewport[0], viewport[1], viewport[2], viewport[3]);
// Did we find any trackables this frame?
for (int tIdx = 0; tIdx < state.getNumTrackableResults(); tIdx++)
{
// Get the trackable:
TrackableResult trackableResult = state.getTrackableResult(tIdx);
float[] modelViewMatrix = Tool.convertPose2GLMatrix(
trackableResult.getPose()).getData();
// Choose the texture based on the target name:
int textureIndex = 0;
// Check the type of the trackable:
assert (trackableResult.getType() == MarkerTracker.getClassType());
MarkerResult markerResult = (MarkerResult) (trackableResult);
Marker marker = (Marker) markerResult.getTrackable();
textureIndex = marker.getMarkerId();
float[] modelViewProjection = new float[16];
Matrix.translateM(modelViewMatrix, 0, -kLetterTranslate, -kLetterTranslate, 0.f);
Matrix.scaleM(modelViewMatrix, 0, kLetterScale, kLetterScale, kLetterScale);
Matrix.multiplyMM(modelViewProjection, 0, vuforiaAppSession.getProjectionMatrix().getData(), 0, modelViewMatrix, 0);
SampleUtils.checkGLError("FrameMarkers render frame");
cam.view.idt();
cam.projection.idt();
cam.combined.idt();
Matrix4 temp3 = new Matrix4(modelViewProjection);
modelInstanceHouse.transform.set(temp3);
modelInstanceHouse.transform.scale(0.05f, 0.05f, 0.05f);
controller.update(Gdx.graphics.getDeltaTime());
modelBatch.render(modelInstanceHouse);
}
GLES20.glDisable(GLES20.GL_DEPTH_TEST);
modelBatch.end();
}
It´s a lot of code, but I hope it helps the people that try to start integrating both libraries. I don´t think this is efficient but it´s the only solution I´ve come with.
Pablo's answer is pretty good, however, if you are interested in a bit different approach (Calling Vuforia from LibGDX, not the other way) and a more complete example, here is a github repo with a simple 3D model renderer.

how to rotate a spatial with physics control in JmonkeyEngine3?

I loaded a 3D model from asset Manager and add CharacterControl as a control. every thing was working correctly but when I tried to rotate the model it did`nt work.
private CharacterControl player;
private Spatial model;
public static final Quaternion YAW045 = new Quaternion().fromAngleAxis(FastMath.PI/4, new Vector3f(0,1,0));
#Override
public void simpleInitApp() {
// add bullet app sate to state manager
bulletAppState = new BulletAppState();
stateManager.attach(bulletAppState);
bulletAppState.getPhysicsSpace().enableDebug(assetManager);
this.addModel();
}
private void addModel(){
model = assetManager.loadModel("Models/Oto/Oto.mesh.j3o");
model.setLocalTranslation(new Vector3f(0,10,0));
capsuleShape = new CapsuleCollisionShape(1f, 7.9f, 1);
player = new CharacterControl(capsuleShape, 1f);
bulletAppState.getPhysicsSpace().add(player);
model.addControl(player);
rootNode.attachChild(model);
model.rotate(YAW045);
}
please help me.
Richard is right.
The CharacterControl class has a setViewDirection() method.
You should really be switching to BetterCharacterControl though as it has better integration. I don't know why CharacterControl is not deprecated.
In general physics objects has a separate "life" as they live in the Bullet PhysicsSpace. For instance the other common physics control: RigidBodyControl class has a setPhysicsRotation(Quaternion rotation) method (just like it has a setPhysicsLocation() method).
More info is in the wiki (although it references CharacterControl) :
Walking Character

Using rectangles to simulate straight line motion of an object

I am relatively new to Java and have been trying to simulate the motion of an object (say a car) on a straight path.
I want my object to move in steps in the output, instead of appearing just at the last point of the line.
I have used 2 classes :Veh.java - the vehicle object and SimuFrame.java - to create the simulation environment.
I have referred to some online tutorials for ideas: http://www.newthinktank.com/2012/07/java-video-tutorial-52/ (This simulates the asteroids game. Howeer I want my object to move in a straight line instead of in a random direction)
Please help me understand where I am wrong and what to do next..
Thanks a lot.
Here's my code:
import java.awt.*;
import java.awt.event.*;
public class Veh extends Rectangle{
int uLeftX, uLeftY; //upper LH Position for Rectangle
static int height = 20;
static int width = 20;
int[] pathCoords=new int[1000];
int startPosY; // start position of the objet - anywhere on the left bounday of the frame.
int goalPosY; // end position of the objet - anywhere on the right boundary of the frame.
//Constructor to Create a new Veh
public Veh(int startPosY,int goalPosY){
//Create a new rectangle vehicle from super class constructor
super(0, startPosY, height, width);
this.startPosY=startPosY;
this.goalPosY=goalPosY;
this.pathCoords = Pathmove();
}
//Calculating the 1000 points on the line joining (0,startPosY) and (goalPosY,999)
int[] Pathmove(){
//Slope calculation
float s=(float)(this.goalPosY-this.startPosY)/999;
pathCoords[0]=this.startPosY;
System.out.println("First xy pair is: 0," +this.pathCoords[0]);
for(int m=1; m<1000; m++){
pathCoords[m]= (int)(m*s)-(int)((m-1)*s)+ pathCoords[m-1];
}
return pathCoords;
}
//Function to move the Reactangular object along the line using the Y coordinate values from Pathmove()
void move(){
int[] a = (int[])this.pathCoords.clone();
for (int c=0; c<a.length;c++){
this.setLocation(c,a[c]);
}
}
}
This is the code for creating the simulation environment.
import javax.swing.*;
import java.awt.*;
import java.util.*;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
public class SimuFrame extends JFrame{
public static int frameWidth=1000;
public static int frameHeight=1000;
public static void main(String[] args){
new SimuFrame();
}
public SimuFrame(){
this.setSize(frameWidth,frameHeight);
this.setTitle("Path Planning Results");
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
SimuObject SO=new SimuObject();
this.add(SO);
// Used to execute code after a given delay
// The attribute is corePoolSize - the number of threads to keep in
// the pool, even if they are idle
ScheduledThreadPoolExecutor executor= new ScheduledThreadPoolExecutor(5);
executor.scheduleAtFixedRate(new RepaintTheFrame(this), 0L, 20L, TimeUnit.MILLISECONDS);
this.setVisible(true);
}
}
// Class implements the runnable interface
// By creating this thread I want to continually redraw the screen
// while other code continues to execute
class RepaintTheFrame implements Runnable{
SimuFrame theFrame;
public RepaintTheFrame(SimuFrame theFrame){
}
#Override
public void run() {
theFrame.repaint();
}
}
class SimuObject extends JComponent{
//Holds every Veh created
public ArrayList<Veh> vehs=new ArrayList<Veh>();
public SimuObject(){
int startPosY = (int)(Math.random()*999);
int goalPosY = (int)(Math.random()*999);
vehs.add(new Veh(startPosY,goalPosY));
}
public void paint(Graphics g){
// Allows me to make many settings changes in regards to graphics
Graphics2D graphicSettings = (Graphics2D)g;
// Draw a background that is as big as the Simu board
graphicSettings.setColor(Color.WHITE);
graphicSettings.fillRect(0, 0, getWidth(), getHeight());
// Set rendering rules
graphicSettings.setRenderingHint( RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
// Set the drawing color to red
graphicSettings.setPaint( Color.RED);
// Cycle through all of the Rock objects
for(Veh veh : vehs){
// Move the vehicle
veh.move();
graphicSettings.draw(veh);
}
}
}
You have a number of problems in your code:
You have a (swallowed) NullPointerException (NPE) in RepaintTheFrame.run(), which causes ScheduledThreadPoolExecutor.scheduleAtFixedRate() to run only once, per scheduleAtFixedRate()'s javadoc.
You are moving your car in JComponent.paint().
In any graphical framework, the repaint will be called automatically by the framework, usually on an OS event, e.g. moving the window, moving the mouse over the window, etc.
Your paint() method should only draw. It should not modify your domain model.
Your move() method always ends up with the vehicle at the end. That's probably not your intent. You probably want your move() method to merely increment the car's position.
Moving from a start value to an end value in steps is called interpolation. You want linear interpolation specifically here. Its one of the easiest to grasp.
This page will be of great assistance to you.
Without getting fancy with interpolation, you could just change your move routine like so:
int index =0;
void move(){
//int[] a = (int[])this.pathCoords.clone();
if(index<this.pathCoords.length)
this.setLocation(c,pathCoords[index]);
index+=1;
}
Not sure why you were cloning the array there. It probably isn't necessary.

Java3d Behaviors and movement

I would like to move a sphere in a random direction within a simple universe. How could i achieve this with behaviours by changing the location a small amount frame by frame. The reason I am trying to do this is to produce random movement within the universe and eventually build in simple collision detection between the particles.
Any advice/links would be appreciated
Add a new class that extends Behavior, using this skeleton:
public class XXXBehavior extends Behavior
{
private WakeupCondition wc = new WakeupOnElapsedTimer(1000); // 1000 ms
public void initialize()
{
wakeupOn(wc);
}
public void processStimulus(Enumeration criteria)
{
// Move the shape here
// prepare for the next update
wakeupOn(wc);
}
}
You later need to instantiate the class and add it to the scene graph. You also need to defined the bounds, otherwise nothing will happen!
xxxEffect = new XXXBehavior();
xxxEffect.setSchedulingBounds(bounds);
sceneBG.addChild(xxxEffect);

Categories