I'm getting mixed results trying to render a basic alien that was done in Blender:
I export in to Ogre 3D and load it in Eclipse:
Then when I load it in my code and try to render it the material won't render:
Could you tell me what I must do to achieve the full alien in my scene? The code I use in Jmonkeyengine is
Spatial model3 = assetManager
.loadModel("objects/creatures/alien/alien.mesh.xml");
model3.scale(0.3f, 0.3f, 0.3f);
model3.setLocalTranslation(-40.0f, 3.5f, -20.0f);
rootNode.attachChild(model3);
Update
I've got material files like these from the export:
dev#dev-OptiPlex-745:~$ ls workspace/DungeonWorld2/assets/objects/creatures/alien/
alien.mesh Material.002.material Material.005.material
alien.mesh.xml Material.003.material
alien.skeleton.xml Material.004.material
dev#dev-OptiPlex-745:~$
This material code actually produces a material in the scene but it's not the one from blender:
model3.setMaterial( new Material(assetManager,
"Common/MatDefs/Misc/Unshaded.j3md") );
Result:
However, loading a 3D model of an alephant without defining the material does work:
Spatial elephant = (Spatial) assetManager.loadModel("Models/Elephant/Elephant.mesh.xml");
float scale = 0.05f;
elephant.scale(scale,scale,scale);
elephant.setLocalTranslation(-50.0f, 3.5f, -20.0f);
control = elephant.getControl(AnimControl.class);
control.addListener(this);
channel = control.createChannel();
for (String anim : control.getAnimationNames())
System.out.println("elephant can:"+anim);
The above code correctly renders the elephant so why can't I export a mesh like that for the alien? I tried to explcitly load the material but it's not working for me:
Spatial model3 = assetManager
.loadModel("objects/creatures/alien/alien.mesh.xml");
model3.scale(0.3f, 0.3f, 0.3f);
model3.setLocalTranslation(-40.0f, 3.5f, -20.0f);
model3.setMaterial( new Material(assetManager,
"objects/creatures/alien/alien.material") );
rootNode.attachChild(model3);
The above generates an exception and I don't really know what material file it is that I'm loading and what do to with the two or three other material files that the export generated:
java.lang.ClassCastException: com.jme3.material.MaterialList cannot be cast to com.jme3.material.MaterialDef
at com.jme3.material.Material.<init>(Material.java:116)
at adventure.Main.simpleInitApp(Main.java:309)
at com.jme3.app.SimpleApplication.initialize(SimpleApplication.java:225)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.initInThread(LwjglAbstractDisplay.java:129)
at com.jme3.system.lwjgl.LwjglAbstractDisplay.run(LwjglAbstractDisplay.java:205)
at java.lang.Thread.run(Thread.java:679)
Update
Loading other models this way is working:
BlenderKey blenderKey = new BlenderKey(
"objects/creatures/troll/troll.mesh.xml");
Spatial troll = (Spatial) assetManager.loadModel(blenderKey);
troll.setLocalTranslation(new Vector3f(-145, 15, -10));
rootNode.attachChild(troll);
BlenderKey blenderKey2 = new BlenderKey(
"objects/creatures/spaceman/man.mesh.xml");
Spatial man = (Spatial) assetManager.loadModel(blenderKey2);
man.setLocalTranslation(new Vector3f(-140, 15, -10));
rootNode.attachChild(man);
I get the models inside my game and they look alreight, both the troll and the spaceman that both originally were .blend files.
Now it's much better when I did it over and it is loading the material. The only problem with the alien left now is the holes in the head that was also answered here.
BlenderKey blenderKey = new BlenderKey(
"objects/creatures/alien/alien.mesh.xml");
Spatial alien = (Spatial) assetManager.loadModel(blenderKey);
alien.setLocalTranslation(new Vector3f(-145, 15, -10));
rootNode.attachChild(alien);
You didn't write anything about your material - did you write one and used it correctly? The problem you get seems to be the lack of material to me.
In general you'll need some *.material file and probably some textures (if you used them in Blender). For the beginning you can use one of the materials that come with Ogre, you'll just need to add:
model3.setMaterialName( "Examples/Rockwall" );
Then look if it changes anything. If you still get the problem you can look into 'Ogre.log' file - it's always worth checking because all the errors goes there.
I also see the second problem here - you render the object as 'one sided' while blender probably render is as two-sided mesh, so you get the holes on the head. You can select in the material to be two sided, but it's better (and faster during rendering) to just create your models without the holes :).
Related
i want to render model via JPCT-AE and use the ARToolkit to realizing AR Application.
so , i inject the code as below into the ARToolkit Project:
Matrix projMatrix = new Matrix();
projMatrix.setDump(ARNativeActivity.getProjectM());
projMatrix.transformToGL();
SimpleVector translation = projMatrix.getTranslation();
SimpleVector dir = projMatrix.getZAxis();
SimpleVector up = projMatrix.getYAxis();
cameraController.setPosition(translation);
cameraController.setOrientation(dir, up);
Matrix transformM = new Matrix();
transformM .setDump(ARNativeActivity.getTransformationM());
transformM .transformToGL();
model.clearTranslation();
model.translate(transformM .getTranslation());
dump.setRow(3,0.0f,0.0f,0.0f,1.0f);
model.clearRotation();
model.setRotationMatrix(transformM );
And then , the model can be render on the screen but always lie on the mark in the screen, ever i using model.rotateX/Y/Z( (float)Math.PI/2 );
Actually, the matrix output from the ARToolkit::ARNativeActivity.getTransformationMatrix() is correct, and then i split this 4*4Matrix into translation Matrix and Rotation Matrix and set into the model like this:
model.translate(transformM .getTranslation());
model.setRotationMatrix(transformM );
But still no work.
I would suggest to organize better your code, and work with matrices to separate the transformations to make to your model and the transformations to place the model in the marker.
What I suggest is:
First, use an additional matrix. It may be called modelMatrix, as it will store the transformation done to the model (scale, rotation and translation).
Then, declare all matrices outside this method (it is for performance reasons only, but is recommended), and on each frame simply setIdentity to them:
projMatrix.setIdentity();
transformM.setIdentity();
modelM.setIdentity();
later, make the model transformations on the modelM matrix. This transformations will apply to the model, after placed on the marker.
modelM.rotateZ((float) Math.toRadians(-angle+180));
modelM.translate(movementX, movementY, 0);
then, multiply the modelM matrix by the trasnformM (this means you get all the transformations done, and move and rotate them as the transformM describes, which in our case means that all the transformations done to the model are moved on top of the marker).
//now multiply trasnformationMat * modelMat
modelM.matMul(trasnformM);
And finally, apply the rotation and translation to your model:
model.setRotationMatrix(modelM);
model.setTranslationMatrix(modelM);
so the whole code would look as:
projMatrix.setIdentity();
projMatrix.setDump(ARNativeActivity.getProjectM());
projMatrix.transformToGL();
SimpleVector translation = projMatrix.getTranslation();
SimpleVector dir = projMatrix.getZAxis();
SimpleVector up = projMatrix.getYAxis();
cameraController.setPosition(translation);
cameraController.setOrientation(dir, up);
model.clearTranslation();
model.clearRotation();
transformM.setIdentity();
transformM .setDump(ARNativeActivity.getTransformationM());
transformM .transformToGL();
modelM.setIdentity()
//do whatever you want to your model
modelM.rotateZ((float)Math.toRadians(180));
modelM.matMul(transformM);
model.setRotationMatrix(modelM );
model.setTranslationMatrix(modelM);
I strongly reccomend to look at this tutorial about matrices and OpenGL, it is not about JPCT, but all concepts may apply also to there, and it is what I've used to place correctly models in markers with the ARSimple example as you may see in this blog entry I made.
Hope this helps!
I'm getting this when I load any .obj file with ObjLoader:
How it looks like in real:
How I'm loading it:
ModelInstance instance = new ModelInstance(model);
instance.transform.setToTranslation(-4, 0, 0);
instance.transform.mul(transform.setToRotation(Axis.X,(float)(Math.random()*360)));
Then in onCreate():
Gdx.gl.glClearDepthf(1.0f);
Gdx.gl.glEnable(GL20.GL_DEPTH_TEST);
Gdx.gl.glDepthFunc(GL20.GL_LESS);
Gdx.gl.glDepthRangef(0f, 1f);
Gdx.gl.glEnable(GL20.GL_TEXTURE_2D);
And in render():
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Gdx.gl.glClearColor(.1f, .1f, .1f, 1f);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT | GL20.GL_DEPTH_BUFFER_BIT);
shader.begin(camera, instances.get(i).transform);
modelBatch.begin(camera);
if (environment !=null) modelBatch.render(instances.get(i), environment, shader);
else modelBatch.render(instances.get(i), shader);
modelBatch.end();
shader.end();
Clean source code here:
source code
SOLUTION:
1, probleme was with the .mtl file, copy pasted from the ship.mtl and rewrite
2, probleme was with the camera near, and far plane (0.1 and 1000 is the good)
3, probleme was with the obj file texture, because it flipped on the obj file, solution was to convert g3db with -f
When using the libgdx 3D api (ModelBatch and/or Shader), you should not change the opengl state outside the Shader class. So, enabling/disabling depth test etc. is useless and might result in unpredicted behavior.
You should not use obj files. Instead use fbx-conv and use the g3db or g3dj file format. Also, your model is missing the mtl file, causing the material not to be applied.
You are using your own shader, you should not have to call shader.end(), modelbatch does this for you.
I tried your model (without material obviously) and it renders correctly using the default shader.
Looks more like you've some problems with your normals here. I don't think it's a problem of wrong depth. Depending on your modelling program e.g. blender3D, you could try to recalculate your facenormals and export it again!
You may follow these steps on 3D Studio Max:
Select all your design with CTRL+A (If you use Windows)
Press ALT+G to select Group category near Edit and Tools selection
Make your all work as a group
Try again on your Android application.
It should be done.
I am trying to add a Map to my libgdx app as a proof of concept. It seems that no matter how I make a packfile, the com.badlogic.gdx.graphics.g2d.tiled.TileAtlas constructor TileAtlas(TiledMap map, FileHandle inputDir) will not correctly read it. My Tile Map is simple and has only 2 tiles, and both the external gui and internal system will generate a packed file.
Here's the issue, either I name the packfile with a filename to match one of my images to satisfy line 2 below, or the method errors out. If I add 2 packfiles, one for each name of an image in my tile set, I find the Atlas isn't constructed correctly in memory. What am I missing here? Should there only ever be one tile in a tilemap?
Code from Libgdx:
for (TileSet set : map.tileSets) {
FileHandle packfile = getRelativeFileHandle(inputDir, removeExtension(set.imageName) + " packfile");
TextureAtlas textureAtlas = new TextureAtlas(packfile, packfile.parent(), false);
Array<AtlasRegion> atlasRegions = textureAtlas.findRegions(removeExtension(removePath(set.imageName)));
for (AtlasRegion reg : atlasRegions) {
regionsMap.put(reg.index + set.firstgid, reg);
if (!textures.contains(reg.getTexture())) {
textures.add(reg.getTexture());
}
}
}
com.badlogic.gdx.graphics.g2d.tiled --> It looks like you're using the old tiled API. I don't even think that package exists anymore, so you should probably download a newer version.
Check out this blog article. I haven't used the new API yet, but at a quick glance it looks much easier to load maps.
I have an issue with an achartengine graph - as in this screenshot:
It looks like the X axis is given too much bottom padding, and the values are duplicated (one representation of each value is in the graph proper, and reacts properly to panning, while the other is located at the bottom of the graph view, but can't be manipulated in any way).
Here's the code used to create the graph:
protected void onCreate(Bundle savedInstanceState) {
...
gDataset = new XYMultipleSeriesDataset();
gRenderer = new XYMultipleSeriesRenderer();
gRenderer.setApplyBackgroundColor(true);
gRenderer.setPointSize(10);
chart = new TimeBarChart(gDataset, gRenderer);
graphView = new GraphicalView(this, chart);
graphHolder.addView(graphView);
//Mode is just an internal enum
chart.setDateFormat(curMode == Mode.DAY ? "HH:mm dd.MM.yyyy" : "dd.MM.yyyy");
....
}
And to populate it:
...
//some DB stuff goes here, result is the cursor
curSeries = new XYSeries("");
gDataset.addSeries(curSeries);
XYSeriesRenderer renderer = new XYSeriesRenderer();
renderer.setColor(Color.RED);
renderer.setPointStyle(PointStyle.POINT);
gRenderer.addSeriesRenderer(renderer);
while (!result.isAfterLast()) {
.....
curSeries.add(timestamp,value);
....
}
.....
graphView.invalidate();
graphView.repaint();
And here's the graph holder's view definition in the layout XML (main container is RelativeLayout of course) :
<LinearLayout
android:id="#+id/graphHolder"
android:layout_width="fill_parent"
android:layout_height="200dp"
android:layout_alignParentTop="true"
android:minHeight="200dp">
</LinearLayout>
A couple of things:
I'm using the 0.7 version.
The TimeBarChart class is nothing else than a TimeChart with the simple change to extend BarChart instead. The code is copied from the 0.7 revision. Regardless, I was using ChartFactory#getTimeChartView() previously and the result was the same - so this isn't the cause of the problem.
I've tried checking whether the height layout parameter causes the problem, but that wasn't it as well.
graphHolder is injected by RoboGuice.
the problem was encountered in the 2.3 emulator.
Obviously, I'm doing something wrong, but I'm at a loss what. Any help is greatly appreciated.
PS. I've tried to post it on the achartengine group, but it looks like the mods are hibernating for the winter ;).
I finally had time to reinvestigate this, and figured it out.
The gist:
The bars on the bottom are the legend. I had a bug in my code that caused it to create a series for each datapoint, hence the multiple "bars", in reality legend graphics. The series had no names, which added to the confusion.
Fixing the bug and adding setShowLegend(false) dealed with the issue.
I've discovered this while evaluating AndroidPlot (BTW, I recommend it as an alternative to achartengine, as graphs can be defined in XML, and can be way more liberally customized graphically than the screenshots suggest).
I somehow failed to notice the legend in the achartengine screenshots, but I recognized them in AndroidPlot. And yes, I do feel quite stupid now :).
I am trying to create a gradient fill for a series in an area chart that I am building through the BIRT chart API, but the book "Integrating and Extending BIRT" and the Interwebs seem curiously silent about how to get it to work. It seems no matter what I do, I always get a flat color from the default palette. I've tried using SeriesDefinition.getSeriesPalette().update(Gradient) and even creating my own Palette with the gradient fill in it and setting that on the SeriesDefinition, but to no avail. I've also noticed that if I do not perform a shift() on the Palette, even if it's shift(0), which the Javadocs claim will do nothing, I get NullPointerException when I try to generate the chart:
Caused by: java.lang.NullPointerException
at org.eclipse.birt.chart.render.Area.renderDataPoints(Area.java:521)
at org.eclipse.birt.chart.render.Line.renderSeries(Line.java:570)
at org.eclipse.birt.chart.render.AxesRenderer.renderPlot(AxesRenderer.java:2181)
at org.eclipse.birt.chart.render.AxesRenderer.render(AxesRenderer.java:314)
at org.eclipse.birt.chart.factory.Generator.render(Generator.java:1368)
... 108 more
Here's the latest (non-working) code that I've tried:
Gradient gradient = FillUtil.createDefaultGradient(BirtReportBuilder.COLOR_WHITE);
gradient.setStartColor(ColorDefinitionImpl.WHITE());
gradient.setEndColor(ColorDefinitionImpl.create(76, 116, 131));
gradient.setDirection(90);
SeriesDefinition sdY = SeriesDefinitionImpl.create();
sdY.getQuery().setDefinition("\"Quantity\"");
Palette pal = PaletteImpl.create(gradient);
pal.shift(0);
sdY.setSeriesPalette(pal);
sdY.getSeries().add(as1);
yAxisPrimary.getSeriesDefinitions().add(sdY);
So what's the magic incantation to get the BIRT charting API to use my Gradient as the area fill?
This code works for me, I get a ugly coloured serie...
sdY.getSeriesPalette().update(GradientImpl.create(ColorDefinitionImpl.create(255,255,255), ColorDefinitionImpl.create(200,0,0,150), 90, false));
Hope it will help you ;p