I've already searched multiple forums but still can't find it. Here is the image:
Sample
I have added BlendingAttribute but some (not all) textures still rendered incorrectly. Those pointed faces should be transparent. Here is my snippet:
private void doneLoading() {
terrain = assets.get("xx.g3db", Model.class);
terrainInstance = new ModelInstance(terrain);
for(n = 2; n < terrainInstance.materials.size; n++){
terrainInstance.materials.get(n).set(new BlendingAttribute(GL30.GL_SRC_ALPHA, GL30.GL_ONE_MINUS_SRC_ALPHA)); // this should working for all faces
}
instances.add(terrainInstance);
loading = false;
}
#Override
public void render() {
if (loading && assets.update()) {
doneLoading();
}
personcam.update(Gdx.graphics.getDeltaTime());
Gdx.gl.glViewport(0, 0, Gdx.graphics.getWidth(), Gdx.graphics.getHeight());
Gdx.gl.glTexParameteri(GL30.GL_TEXTURE_2D, GL30.GL_TEXTURE_MAG_FILTER, GL30.GL_NEAREST);
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL30.GL_COLOR_BUFFER_BIT | GL30.GL_DEPTH_BUFFER_BIT);
modelBatch.begin(cam);
modelBatch.render(instances, environment);
modelBatch.end();
}
I have checked my texture files and they are fine. My FBX file (i'm using SketchUp 8) is fine too. Why are some faces not render transparency correctly? Is this bug?
Found by adding a single line:
terrainInstance.materials.get(n).set(new FloatAttribute(FloatAttribute.AlphaTest, 0.8f));
in the for loop fixes the transparency problem.
Related
I have looked everywhere, and I can't seem to get OpenGL to draw a simple quad.
The window shows up fine with the correct color background, but OpenGL just won't draw the box.
I am using OpenGL 4.4.0 - Build 20.19.15.4463
The window size is 1920x1080
This is the code I currently have:
in Main.java:
public void init(){
if(glfwInit() != true){
System.err.println("GLFW failed to initialize");
}
glfwWindowHint(GLFW_RESIZABLE, GL_TRUE);
//TODO change name.
window = glfwCreateWindow(width, height, "GameName", NULL, NULL);
if(window == NULL){
System.err.println("Window failed to be created");
}
GLFWVidMode vidmode = glfwGetVideoMode(glfwGetPrimaryMonitor());
glfwSetWindowPos(window, 100, 100);
glfwMakeContextCurrent(window);
glfwShowWindow(window);
GL.createCapabilities();
glClearColor(0.0f, 0.5f, 1.0f, 1.0f);
glEnable(GL_DEPTH_TEST);
//set up projection matrix; allows us to draw.
glMatrixMode(GL_PROJECTION);
glLoadIdentity();
glOrtho(0, width, height, 0, 1, -1);
glMatrixMode(GL_MODELVIEW);
testBox = new EntityBox(3, Color.RED);//just to test right now
System.out.println("OpenGL: "+ glGetString(GL_VERSION));
}
public void update(){
glfwPollEvents();
}
public void render(){
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glLoadIdentity();
glfwSwapBuffers(window);
testBox.draw();
}
in EntityBox:
public void draw(){
glColor3f(1.0f, 0.0f, 0.0f);
glBegin(GL_QUADS);
glVertex2f(0,0);
glVertex2f(0,100);
glVertex2f(100,0);
glVertex2f(100,100);
glEnd();
}
I fixed it:
glClear needs to be
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
don't know why, because i was tole depth_buffer is used if you want 3d.
and
glfwSwapBuffers(window);
needs to be called after drawing.
I am working on a Libgdx game which loads Tiled maps. The current map I am working on makes use of 2 tilesets, one for shadow/light and another for terrain and buildings. The general process I do, that has been working fine, is that I receive the sprite sheet from the artist, design the maps, then take the spritesheet file and split it using ImageMagick. From there I take the split images and create an optimized png and atlas file with TexturePacker.
However, this is the first map I have made that makes use of multiple tilesets. The issue I am having is when loading the map with AtlasTmxMapLoader it relies on a single atlas file property in the map. My shadows and lighting are split into a separate image and atlas and Id rather not merge them all into one in Tiled (and have to re-do a portion of the map).
Perhaps I am missing something simple. How can I handle multiple tilesets?
So after reading more into how .tmx files are read I was able to fix my problem.
Here is how to properly do it when working with multiple tilesets and re-packing your spritesheets in TexturePacker. First, cut up the tileset images using a utility like ImageMagick and make sure they are indexed (specified by an underscore and number in the filename). You can do this with the crop command in ImageMagick like so:
convert.exe "shrine_tileset.png" -crop 16x16 "shrine_tileset_%02d.png"
Second, re-pack all tiles from all tilesets into a single atlas in TexturePacker. If it works correctly you will see the name of each tileset in the atlas file with an associated index based on the tile id. For example:
shrine_tileset
rotate: false
xy: 382, 122
size: 16, 16
orig: 16, 16
offset: 0, 0
index: 703
Finally (and this is the part I could not figure out), make sure each tileset's tile indexes start from the "firstgid" value in the .tmx file. For example, my second tilesheet starts from 2049, as their are 2048 tiles in the first sheet. This should be denoted at the top of the .tmx file for each tileset.
<tileset firstgid="2049" source="shadow_light.tsx"/>
So when cutting up the tiles for my tileset "shadow_light", I would start them from index 2048, one less than the gid, EX: "shadow_light_2048.png".
Hopefully this helps someone!
I am no LibGDX expert but almost all tilemap renderers I've seen rely on working with 1 tileset. The reason is that they are rendered using OpenGL. The renderer sets the texture and draws all tiles with 1 draw call. You can't switch textures in between.
The best way would be to create 2 (or more) separate layers. Each layer uses 1 tileset. E.g. 1 for the background, 1 for the shadows, 1 for the foreground (e.g. walls).
This issue is fixed in 1.9.11. If you are using an earlier version you can override AtlasTmxMapLoader with a fix.
MyAtlasTmxMapLoader.Java
import com.badlogic.gdx.files.FileHandle;
import com.badlogic.gdx.maps.ImageResolver;
import com.badlogic.gdx.maps.MapProperties;
import com.badlogic.gdx.maps.tiled.AtlasTmxMapLoader;
import com.badlogic.gdx.maps.tiled.TiledMapTile;
import com.badlogic.gdx.maps.tiled.TiledMapTileSet;
import com.badlogic.gdx.utils.Array;
import com.badlogic.gdx.utils.GdxRuntimeException;
import com.badlogic.gdx.utils.SerializationException;
import com.badlogic.gdx.utils.XmlReader.Element;
public class MyAtlasTmxMapLoader extends AtlasTmxMapLoader {
/**
* Same as AtlasTmxMapLoader, but fixed to get the firstid attribute from the tileset element in the TMX file, not tsx file.
*/
#Override
protected void loadTileSet(Element mapElement, FileHandle tmxFile, ImageResolver imageResolver) {
if (mapElement.getName().equals("tileset")) {
String imageSource = "";
int imageWidth = 0;
int imageHeight = 0;
FileHandle image = null;
Element element = null;
String source = mapElement.getAttribute("source", null);
if (source != null) {
FileHandle tsx = getRelativeFileHandle(tmxFile, source);
try {
element = xml.parse(tsx);
Element imageElement = element.getChildByName("image");
if (imageElement != null) {
imageSource = imageElement.getAttribute("source");
imageWidth = imageElement.getIntAttribute("width", 0);
imageHeight = imageElement.getIntAttribute("height", 0);
image = getRelativeFileHandle(tsx, imageSource);
}
} catch (SerializationException e) {
throw new GdxRuntimeException("Error parsing external tileset.");
}
} else {
Element imageElement = mapElement.getChildByName("image");
if (imageElement != null) {
imageSource = imageElement.getAttribute("source");
imageWidth = imageElement.getIntAttribute("width", 0);
imageHeight = imageElement.getIntAttribute("height", 0);
image = getRelativeFileHandle(tmxFile, imageSource);
}
}
String name = element.get("name", null);
// Get the firstid attribute from the tileset element in the TMX file, not tsx file.
int firstgid = mapElement.getIntAttribute("firstgid", 1);
int tilewidth = element.getIntAttribute("tilewidth", 0);
int tileheight = element.getIntAttribute("tileheight", 0);
int spacing = element.getIntAttribute("spacing", 0);
int margin = element.getIntAttribute("margin", 0);
Element offset = element.getChildByName("tileoffset");
int offsetX = 0;
int offsetY = 0;
if (offset != null) {
offsetX = offset.getIntAttribute("x", 0);
offsetY = offset.getIntAttribute("y", 0);
}
TiledMapTileSet tileSet = new TiledMapTileSet();
// TileSet
tileSet.setName(name);
final MapProperties tileSetProperties = tileSet.getProperties();
Element properties = element.getChildByName("properties");
if (properties != null) {
loadProperties(tileSetProperties, properties);
}
tileSetProperties.put("firstgid", firstgid);
// Tiles
Array<Element> tileElements = element.getChildrenByName("tile");
addStaticTiles(tmxFile, imageResolver, tileSet, element, tileElements, name, firstgid, tilewidth,
tileheight, spacing, margin, source, offsetX, offsetY, imageSource, imageWidth, imageHeight, image);
for (Element tileElement : tileElements) {
int localtid = tileElement.getIntAttribute("id", 0);
TiledMapTile tile = tileSet.getTile(firstgid + localtid);
if (tile != null) {
addTileProperties(tile, tileElement);
addTileObjectGroup(tile, tileElement);
addAnimatedTile(tileSet, tile, tileElement, firstgid);
}
}
map.getTileSets().addTileSet(tileSet);
}
}
}
And then call:
new MyAtlasTmxMapLoader().load(pathname)
Source: [Tutorial] Using multiple Tilesets with Libgdx and Tiled
I am trying to lightly customise by inheritance some Elements in Mvvmcross Dialog implementation.
Colors and fonts are getting set fine, but if I try to set the Text Labels frame (to 100 X ... in this example) I cannot get it to stick.
Can anyone point me in the direction of where I am going wrong here? tried it in a couple different places.
public class MyBooleanElement : BooleanElement {
public MyBooleanElement (string caption) : base(caption, false)
{
}
protected override UISwitch CreateSwitch()
{
UISwitch s = base.CreateSwitch();
s.BackgroundColor = UIColor.Clear;
s.Opaque = false;
s.Layer.Opacity = 0.25f;
return s;
}
protected override UITableViewCell GetCellImpl(UITableView tv)
{
var cell = base.GetCellImpl(tv);
if (cell.BackgroundColor != UIColor.Clear) {
cell.BackgroundColor = UIColor.Clear;
cell.TextLabel.Font = Theme.GetContentFont();
cell.TextLabel.TextColor = UIColor.White;
cell.TextLabel.Frame = new RectangleF(100, 0, 320, 20); // this is not holding, resets to 15
cell.ContentView.Frame = new RectangleF(50, cell.ContentView.Frame.Top, cell.ContentView.Frame.Width, cell.ContentView.Frame.Height); // try this also?
}
return cell;
}
protected override void UpdateCaptionDisplay(UITableViewCell cell)
{
base.UpdateCaptionDisplay(cell);
if (cell != null) {
cell.TextLabel.Frame = new RectangleF(100, 0, 320, 20); // this is not holding, resets to 15
cell.TextLabel.BackgroundColor = UIColor.Blue; // Yet this works? some constraints somewhere cannot see in source!
}
}
}
The dialog part of the framework is positioning the headers (labels) and controls for you.
You should look at the source code a bit, maybe try to understand how it works a little bit.
You can start with a breakpoint and step into the source code while debugging. I'm sure you are going to see where the 15 value is being set.
I'm sorry I can't give you an exact answer. I had some issues myself with the incorrect positioning of dialog elements on iPad, and I had to dig a bit.
I wanted to mask some nodes of my DisplayObject tree. I couldn't make masking work in my big project. So I build a simple example for me and I saw it works actually pretty good. But I can't figure out why it doesn't work in my big project. All my visible objects are Sprites or from classes that extend Sprite.
masking in big project doesn't work
I can see the normal state of my nodeToBeMasked
when I add the mask to this node I can see the mask
but when I set the mask to be the mask, I continue to see everything (pure nodeToBeMasked is masked but not the children - which would be much more important)
masking in simple example works fine
How can masking stop working ?
Code: (that doesn't work, big project)
// custom class extends Sprite
override protected function onAddToStage(event:Event):void
{
trace(stage); // stage exists
var maskSprite:Sprite = new Sprite();
maskSprite.graphics.beginFill(0xffff00, 1);
maskSprite.graphics.drawCircle(0, 0, 64);
maskSprite.graphics.endFill();
maskSprite.x = 64;
maskSprite.y = 64;
if (true)
{
this.addChild(maskSprite); // doesn't help
this.mask = maskSprite; // I can see EVERYTHING here, inside and outside the cirle
}
else
addChild(maskSprite); // I can see the mask here
}
Code: (that works)
[SWF(frameRate="60",backgroundColor="0xffffff",width="128",height="128")]
public class MaskTest extends Sprite
{
public function MaskTest()
{
addEventListener(Event.ADDED_TO_STAGE, onAddedToStage);
}
private function onAddedToStage(event: Event): void
{
trace(stage);
// this
graphics.beginFill(0x00ff00, 1);
graphics.drawRect(8, 8, 112, 112);
graphics.endFill();
// extra childs <- ^^
for (var i: int = 0; i < 100; i++)
{
var child: Sprite = new Sprite();
child.graphics.beginFill(uint(Math.random() * 0x1000000), 1);
child.graphics.drawRect(Math.random() * 64, Math.random() * 64, 64, 64);
child.graphics.endFill();
addChild(child);
}
// mask
var maskSprite: Sprite = new Sprite();
maskSprite.graphics.beginFill(0xffff00, 1);
maskSprite.graphics.drawCircle(0, 0, 64);
maskSprite.graphics.endFill();
maskSprite.x = 64;
maskSprite.y = 64;
// switch to check the mask
if (true)
this.mask = maskSprite;
else
addChild(maskSprite);
}
}
Update:
I found out that my custom class (that is the root and is only responsible for Event.ENTER_FRAME updates) was causing the problem. I don't know why but by disabling the z update in all my project solved the children of my maskedNode not being masked.
The mask MUST be added to the parent to work, not only used as
obj.mask = myMask; //This will not work alone
To make it work, it must be added to the parent object display list
obj.addChild(myMask);
obj.mask = myMask;
//this wasthe problem in my big project
maskSprite.z = 0; // avoid this with masks
Just a wild guess from me:if you use the properties z, rotationX, rotationY, rotationZ (maybe some more) the sprite is shifted to the 3D space and the masking is only working in 2D.
I have experimented with Flash 3D a bit. The transition from 2D to 3D seemed very smooth. You can't see when they "turn".
I managed to pack a textureatlas with images i have and it works properly in that it creates the .pack file and the .png file. The issue is when i load the texture atlas and try to assign AtlasRegions. it loads the entire atlas instead of only the image i want. here is a mockup code i used to test it.
#Override
public void create() {
camera = new OrthographicCamera(800, 480);
batch = new SpriteBatch();
test = new TextureAtlas(Gdx.files.internal("polytest.png"));
sprite = test.findRegion("hero");
texture = new Texture(Gdx.files.internal("data/libgdx.png"));
texture.setFilter(TextureFilter.Linear, TextureFilter.Linear);
}
#Override
public void render() {
Gdx.gl.glClearColor(1, 1, 1, 1);
Gdx.gl.glClear(GL10.GL_COLOR_BUFFER_BIT);
batch.setProjectionMatrix(camera.combined);
batch.begin();
batch.draw(sprite.getTexture(), 10, 10);
batch.end();
}
this renders the entire atlas instead of only the image called "hero" in the atlas. Why does this happen?
Thanks in advance.
When you do.-
batch.draw(sprite.getTexture(), 10, 10);
you're actually telling libgdx to render the whole Texture. What you need is to draw just the TextureRegion.-
batch.draw(sprite, 10, 10);