Mipmap generation

Hey everyone,

recently @iwgeric wrote to me about mipmap generation issue in blender importer.

At this moment Trilinear mode for mipmaps is always used for the newly imported texture.
But @iwgeric says that this causes too much memory usage on android system and suggest to use the blender option for mipmap generation.
There is an option for a texture that causes mipmap generation and I can easily read it.

I have made a few simple changes to the code.
I added the enum in BlenderKey:
[java]
public static enum MipmapGenerationMethod {
NEVER_GENERATE,
ALWAYS_GENERATE,
GENERATE_WHEN_NEEDED;
}
[/java]
along with proper variable in the BlenderKey class with the default value set to: GENERATE_WHEN_NEEDED.

Using this enum can ensure that the mipmaps are generated when the proper flag in blender file is set.

And my question is: shall I commit the code ?
Because someone left the note in the source code of TextureHelper to ALWAYS generate mipmaps for all textures.

This confused me and that is why I’d like to have your opinion on the matter.

Cheers,
Kaelthas

4 Likes

Its okay to add this, import of blender models is quite specific and the way of setting the options via the Key works out well, also in the SDK. Just make the default use MipMaps. The comment is more about the common render situations on desktop.

1 Like

@Kaelthas

Thanks for looking into this.

@Kaelthas said: There is an option for a texture that causes mipmap generation and I can easily read it. Using this enum can ensure that the mipmaps are generated when the proper flag in blender file is set.

What flag in Blender will you use? The “MIP Map” checkbox?

@iwgeric said: What flag in Blender will you use? The "MIP Map" checkbox?

Yes.

@normen said: Just make the default use MipMaps.

By saying ‘default use’ you mean GENERATE_WHEN_NEEDED or ALWAYS_GENERATE option to be set ?
I think that GENERATE_WHEN_NEEDED would be better. The mipmap option is set in blender by default when you create new
texture. So if the user will not want mips then he will need to check this option out intentionally.

2 Likes

Yeah, so use when_needed

OK, I’ve just commited the change.
Enjoy :wink:

2 Likes

@Kaelthas

Does this also need to be changed based on the setting in blender?

http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureHelper.java?spec=svn10201&r=10201#730

I have already changed that.
This method now loads only image. The texture is created in one method only now. :wink:

1 Like

Cool, did you make the change to add the original texture key to the texture again? Its important.

@Kaelthas

I tried testing this change. It looks like the mipmaps are not being generated when the texture is rendered (good). However, Android is not creating the Android Bitmap and compressing the image before loading to the GPU. It’s just sending the byte data for the image directly. This usually happens because the image data is packed inside the j3o file instead of staying as a separate file. Is it possible that one of the fixes is now causing the image to be packed inside the j3o?

I fixed that here: http://code.google.com/p/jmonkeyengine/source/detail?r=10230 It was because of the loader losing the texture keys on import, hence the exporter could not reference the files and stored the image data in the j3o file.

1 Like

@normen

Now you created a dead code.

[java]
Texture result = new Texture2D((Image) blenderContext.getLoadedFeature(image.getOldMemoryAddress(), LoadedFeatureDataType.LOADED_FEATURE));
if (result == null) {
//this will never be executed and here is the image loading performed either from image file or from inside the blender file
}
[/java]

And besides that you cannot be sure that this:
[java]
(Image) blenderContext.getLoadedFeature(image.getOldMemoryAddress(), LoadedFeatureDataType.LOADED_FEATURE)
[/java]
will not return null because the image might not yet have been loaded into blender context. This will give you NullPointerException.

Well fix it then, that part I only had to change cause you didn’t react to the topic anymore… Do you understand the purpose of this change?

OK I made a fix for the dead code and NullPointerException that occured when loading textures.

Please check it out if everything is fine now :slight_smile:

I guess I will need to add tests of saving and loading the data to and from jme3 format files after importing the model :wink:

2 Likes

Cool, thanks. Yes, definitely make a test like the following: register some folder locator to a folder with subfolders in the assetManager, load the model and its texture from the subfolder (e.g. loadModel(“Models/MyModel/MyModel.blender”):wink: and then store a j3o file in the same folder. Then load that j3o file again. It should be able to reference the textures by the full pathname of the textures that was used when loading the blend model, e.g. Models/MyModel/MyTexture.jpg. If its not, it will store the texture in the j3o.

Referenced textures are the #1 use case, packed or generated textures not so much really so these are what definitely has to work .

1 Like

@Kaelthas / @Normen

I spent some time on this today. My blend file has the MIP Maps checkbox unchecked and the images are external to the blend file.

The minFilter is still the default (no mipmaps) - Good
The texture is creating the Android Bitmap and applying compression - Good
The renderer is still generating mipmaps - Not so good

The TextureKey created in TextureHelper sets GenerateMips true which is causing the renderer to create the additional images. Can the line from TextureHelper that blindly sets generateMips(true) be removed? I think that is the last step.

http://code.google.com/p/jmonkeyengine/source/browse/trunk/engine/src/blender/com/jme3/scene/plugins/blender/textures/TextureHelper.java#728

Below is the log from Android when a texture is updated by the renderer.

[java]
OGLESShaderRenderer: INFO OGLESShaderRenderer 5:22:38 PM updating image for texture: turn90left
OGLESShaderRenderer: INFO OGLESShaderRenderer 5:22:38 PM Texture minFilter: NearestNoMipMaps
OGLESShaderRenderer: INFO OGLESShaderRenderer 5:22:38 PM TextureKey GenerateMips: true
OGLESShaderRenderer: INFO OGLESShaderRenderer 5:22:38 PM Image hasMipMaps: false
OGLESShaderRenderer: INFO OGLESShaderRenderer 5:22:38 PM Image MipMapSizes: null
OGLESShaderRenderer: INFO OGLESShaderRenderer 5:22:38 PM Image GeneratedMipmapsRequired: true
OGLESShaderRenderer: INFO OGLESShaderRenderer 5:22:38 PM Image MipmapsGenerated: true
TextureUtil: INFO TextureUtil 5:22:38 PM === Uploading image Image[size=512x512, format=RGBA8, id=350005]. Using BITMAP PATH ===
TextureUtil: - Generating mipmaps for bitmap using SOFTWARE
TextureUtil: INFO TextureUtil 5:22:38 PM - Uploading LOD level 0 (512x512) with compression.
TextureUtil: INFO TextureUtil 5:22:39 PM - Uploading LOD level 1 (256x256) with compression.
TextureUtil: INFO TextureUtil 5:22:39 PM - Uploading LOD level 2 (128x128) with compression.
TextureUtil: INFO TextureUtil 5:22:39 PM - Uploading LOD level 3 (64x64) with compression.
TextureUtil: INFO TextureUtil 5:22:39 PM - Uploading LOD level 4 (32x32) with compression.
TextureUtil: INFO TextureUtil 5:22:39 PM - Uploading LOD level 5 (16x16) with compression.
TextureUtil: INFO TextureUtil 5:22:39 PM - Uploading LOD level 6 (8x8) with compression.
TextureUtil: INFO TextureUtil 5:22:39 PM - Uploading LOD level 7 (4x4) with compression.
TextureUtil: INFO TextureUtil 5:22:39 PM - Uploading LOD level 8 (2x2) with compression.
TextureUtil: INFO TextureUtil 5:22:39 PM - Uploading LOD level 9 (1x1) with compression.
AndroidImageInfo: Bitmap was deleted.
[/java]

1 Like

Ooops,

looks like I missed that one :slight_smile:

I removed it and made a commit a moment ago.

2 Likes

Looks like we have a winner. Thanks a lot for working on this!