Added support for gpu skinning. Added animation system.

This commit is contained in:
2014-05-27 13:45:58 -04:30
parent 5ef7928706
commit 686f263b0d
4 changed files with 176 additions and 51 deletions

View File

@@ -0,0 +1,44 @@
/*
* Copyright (C) 2014 Miguel Angel Astor Romero
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package ve.ucv.ciens.ccg.nxtar.components;
import java.util.LinkedList;
import java.util.List;
import com.artemis.Component;
import com.badlogic.gdx.graphics.g3d.ModelInstance;
import com.badlogic.gdx.graphics.g3d.utils.AnimationController;
public class AnimationComponent extends Component {
public AnimationController controller;
public List<String> animationsIds;
public int current;
public int next;
public AnimationComponent(ModelInstance instance) throws IllegalArgumentException{
if(instance == null)
throw new IllegalArgumentException("Instance is null.");
controller = new AnimationController(instance);
animationsIds = new LinkedList<String>();
current = -1;
next = -1;
for(int i = 0; i < instance.animations.size; i++){
animationsIds.add(instance.animations.get(i).id);
}
}
}

View File

@@ -19,6 +19,7 @@ import com.badlogic.gdx.Gdx;
import com.badlogic.gdx.graphics.Camera;
import com.badlogic.gdx.graphics.Color;
import com.badlogic.gdx.graphics.GL20;
import com.badlogic.gdx.graphics.VertexAttributes;
import com.badlogic.gdx.graphics.g3d.Renderable;
import com.badlogic.gdx.graphics.g3d.Shader;
import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
@@ -30,59 +31,100 @@ import com.badlogic.gdx.math.Vector3;
import com.badlogic.gdx.utils.GdxRuntimeException;
public class SingleLightPerPixelShader implements Shader{
private static final String VERTEX_SHADER_PATH = "shaders/directionalPerPixelSingleLight/directionalPerPixel_vert.glsl";
private static final String FRAGMENT_SHADER_PATH = "shaders/directionalPerPixelSingleLight/directionalPerPixel_frag.glsl";
private static final int MAX_NUM_BONES = 4;
private static final Matrix4 IDENTITY = new Matrix4();
private static final String VERTEX_SHADER_PATH = "shaders/directionalPerPixelSingleLight/directionalPerPixel_vert.glsl";
private static final String FRAGMENT_SHADER_PATH = "shaders/directionalPerPixelSingleLight/directionalPerPixel_frag.glsl";
private static final String INCLUDE_SKINNING = "#define SKINNING\n";
private ShaderProgram program;
private ShaderProgram skinningProgram;
private ShaderProgram baseProgram;
private Camera camera;
private RenderContext context;
private Matrix4 normalMatrix;
// Uniform locations.
private int u_geomTrans;
private int u_projTrans;
private int u_lightPos;
private int u_lightDiffuse;
private int u_specular;
private int u_ambient;
private int u_shiny;
private int u_cameraPos;
private int u_materialDiffuse;
private int u_normalMatrix;
private int[] u_geomTrans;
private int[] u_projTrans;
private int[] u_lightPos;
private int[] u_lightDiffuse;
private int[] u_specular;
private int[] u_ambient;
private int[] u_shiny;
private int[] u_cameraPos;
private int[] u_materialDiffuse;
private int[] u_normalMatrix;
private int[] u_bones;
public SingleLightPerPixelShader(){
program = null;
camera = null;
context = null;
skinningProgram = null;
baseProgram = null;
camera = null;
context = null;
}
@Override
public void init() throws GdxRuntimeException{
normalMatrix = new Matrix4().idt();
u_bones = new int[MAX_NUM_BONES];
// Compile the shader.
program = new ShaderProgram(Gdx.files.internal(VERTEX_SHADER_PATH), Gdx.files.internal(FRAGMENT_SHADER_PATH));
String vertexCode = Gdx.files.internal(VERTEX_SHADER_PATH).readString();
String fragmentCode = Gdx.files.internal(FRAGMENT_SHADER_PATH).readString();
if(!program.isCompiled())
throw new GdxRuntimeException(program.getLog());
skinningProgram = new ShaderProgram(INCLUDE_SKINNING + vertexCode, fragmentCode);
baseProgram = new ShaderProgram(vertexCode, fragmentCode);
if(!skinningProgram.isCompiled())
throw new GdxRuntimeException(skinningProgram.getLog());
if(!baseProgram.isCompiled())
throw new GdxRuntimeException(skinningProgram.getLog());
// Create uniform locations.
u_projTrans = new int[2];
u_geomTrans = new int[2];
u_lightPos = new int[2];
u_lightDiffuse = new int[2];
u_specular = new int[2];
u_ambient = new int[2];
u_shiny = new int[2];
u_cameraPos = new int[2];
u_materialDiffuse = new int[2];
u_normalMatrix = new int[2];
// Cache uniform locations.
u_projTrans = program.getUniformLocation("u_projTrans");
u_geomTrans = program.getUniformLocation("u_geomTrans");
u_lightPos = program.getUniformLocation("u_lightPos");
u_lightDiffuse = program.getUniformLocation("u_lightDiffuse");
u_specular = program.getUniformLocation("u_specular");
u_ambient = program.getUniformLocation("u_ambient");
u_shiny = program.getUniformLocation("u_shiny");
u_cameraPos = program.getUniformLocation("u_cameraPos");
u_materialDiffuse = program.getUniformLocation("u_materialDiffuse");
u_normalMatrix = program.getUniformLocation("u_normalMatrix");
u_projTrans [0] = skinningProgram.getUniformLocation("u_projTrans");
u_geomTrans [0] = skinningProgram.getUniformLocation("u_geomTrans");
u_lightPos [0] = skinningProgram.getUniformLocation("u_lightPos");
u_lightDiffuse [0] = skinningProgram.getUniformLocation("u_lightDiffuse");
u_specular [0] = skinningProgram.getUniformLocation("u_specular");
u_ambient [0] = skinningProgram.getUniformLocation("u_ambient");
u_shiny [0] = skinningProgram.getUniformLocation("u_shiny");
u_cameraPos [0] = skinningProgram.getUniformLocation("u_cameraPos");
u_materialDiffuse [0] = skinningProgram.getUniformLocation("u_materialDiffuse");
u_normalMatrix [0] = skinningProgram.getUniformLocation("u_normalMatrix");
u_projTrans [1] = baseProgram.getUniformLocation("u_projTrans");
u_geomTrans [1] = baseProgram.getUniformLocation("u_geomTrans");
u_lightPos [1] = baseProgram.getUniformLocation("u_lightPos");
u_lightDiffuse [1] = baseProgram.getUniformLocation("u_lightDiffuse");
u_specular [1] = baseProgram.getUniformLocation("u_specular");
u_ambient [1] = baseProgram.getUniformLocation("u_ambient");
u_shiny [1] = baseProgram.getUniformLocation("u_shiny");
u_cameraPos [1] = baseProgram.getUniformLocation("u_cameraPos");
u_materialDiffuse [1] = baseProgram.getUniformLocation("u_materialDiffuse");
u_normalMatrix [1] = baseProgram.getUniformLocation("u_normalMatrix");
for(int i = 0; i < MAX_NUM_BONES; i++){
u_bones[i] = skinningProgram.getUniformLocation("u_bone" + Integer.toString(i));
}
}
@Override
public void dispose(){
if(program != null)
program.dispose();
if(skinningProgram != null) skinningProgram.dispose();
if(baseProgram != null) baseProgram.dispose();
}
@Override
@@ -118,11 +160,6 @@ public class SingleLightPerPixelShader implements Shader{
this.camera = camera;
this.context = context;
program.begin();
// Set camera dependant uniforms.
program.setUniformMatrix(u_projTrans, this.camera.combined);
program.setUniformf(u_cameraPos, this.camera.position);
// Set render context.
this.context.setDepthTest(GL20.GL_LEQUAL);
@@ -131,6 +168,10 @@ public class SingleLightPerPixelShader implements Shader{
@Override
public void render(Renderable renderable){
ShaderProgram program;
int index;
boolean bonesEnabled;
// Get material colors.
Vector3 lightPosition = renderable.environment.directionalLights.get(0).direction;
Color diffuseLightColor = renderable.environment.directionalLights.get(0).color;
@@ -139,24 +180,49 @@ public class SingleLightPerPixelShader implements Shader{
Color ambientColor = ((ColorAttribute)renderable.environment.get(ColorAttribute.AmbientLight)).color;
float shininess = ((FloatAttribute)renderable.material.get(FloatAttribute.Shininess)).value;
// Set model dependant uniforms.
program.setUniformMatrix(u_geomTrans, renderable.worldTransform);
program.setUniformMatrix(u_normalMatrix, normalMatrix.idt().mul(renderable.worldTransform).inv().tra());
program.setUniformf(u_lightPos, lightPosition);
program.setUniformf(u_lightDiffuse, diffuseLightColor);
program.setUniformf(u_materialDiffuse, diffuseColor);
program.setUniformf(u_specular, specularColor);
program.setUniformf(u_ambient, ambientColor);
program.setUniformf(u_shiny, shininess);
if(renderable.mesh.getVertexAttribute(VertexAttributes.Usage.BoneWeight) != null){
program = skinningProgram;
index = 0;
bonesEnabled = true;
}else{
program = baseProgram;
index = 1;
bonesEnabled = false;
}
program.begin();
// Set camera dependant uniforms.
program.setUniformMatrix(u_projTrans[index], this.camera.combined);
program.setUniformf(u_cameraPos[index], this.camera.position);
// Set model dependant uniforms.
program.setUniformMatrix(u_geomTrans[index], renderable.worldTransform);
program.setUniformMatrix(u_normalMatrix[index], normalMatrix.idt().mul(renderable.worldTransform).inv().tra());
program.setUniformf(u_lightPos[index], lightPosition);
program.setUniformf(u_lightDiffuse[index], diffuseLightColor);
program.setUniformf(u_materialDiffuse[index], diffuseColor);
program.setUniformf(u_specular[index], specularColor);
program.setUniformf(u_ambient[index], ambientColor);
program.setUniformf(u_shiny[index], shininess);
// Set the bones uniforms.
if(bonesEnabled){
for(int i = 0; i < MAX_NUM_BONES; i++){
if(renderable.bones != null && i < renderable.bones.length && renderable.bones[i] != null)
skinningProgram.setUniformMatrix(u_bones[i], renderable.bones[i]);
else
skinningProgram.setUniformMatrix(u_bones[i], IDENTITY);
}
}
// Render.
renderable.mesh.render(program, renderable.primitiveType, renderable.meshPartOffset, renderable.meshPartSize);
program.end();
}
@Override
public void end(){
program.end();
this.camera = null;
this.context = null;
}

View File

@@ -27,6 +27,7 @@ import ve.ucv.ciens.ccg.nxtar.graphics.RenderParameters;
import ve.ucv.ciens.ccg.nxtar.interfaces.ImageProcessor.MarkerData;
import ve.ucv.ciens.ccg.nxtar.network.monitors.MotorEventQueue;
import ve.ucv.ciens.ccg.nxtar.network.monitors.VideoFrameMonitor;
import ve.ucv.ciens.ccg.nxtar.systems.AnimationSystem;
import ve.ucv.ciens.ccg.nxtar.systems.MarkerPositioningSystem;
import ve.ucv.ciens.ccg.nxtar.systems.MarkerRenderingSystem;
import ve.ucv.ciens.ccg.nxtar.systems.ObjectRenderingSystem;
@@ -191,14 +192,19 @@ public class InGameState extends BaseState{
// Set up the game world.
gameWorld = new World();
entityCreator = new MarkerTestEntityCreator();
entityCreator.setWorld(gameWorld);
entityCreator.createAllEntities();
gameWorld.setSystem(new MarkerPositioningSystem());
gameWorld.setSystem(new AnimationSystem());
markerRenderingSystem = new MarkerRenderingSystem(modelBatch);
objectRenderingSystem = new ObjectRenderingSystem(modelBatch);
gameWorld.setSystem(markerRenderingSystem, true);
gameWorld.setSystem(objectRenderingSystem, true);
gameWorld.initialize();
}

View File

@@ -15,23 +15,32 @@
*/
package ve.ucv.ciens.ccg.nxtar.systems;
import ve.ucv.ciens.ccg.nxtar.components.ModelComponent;
import ve.ucv.ciens.ccg.nxtar.components.AnimationComponent;
import com.artemis.Aspect;
import com.artemis.ComponentMapper;
import com.artemis.Entity;
import com.artemis.annotations.Mapper;
import com.artemis.systems.EntityProcessingSystem;
import com.badlogic.gdx.Gdx;
public class AnimationSystem extends EntityProcessingSystem {
@Mapper ComponentMapper<AnimationComponent> animationMapper;
@SuppressWarnings("unchecked")
public AnimationSystem(){
super(Aspect.getAspectForAll(ModelComponent.class));
super(Aspect.getAspectForAll(AnimationComponent.class));
}
@Override
protected void process(Entity e) {
// TODO Auto-generated method stub
AnimationComponent animation = animationMapper.get(e);
if(animation.current != animation.next){
animation.controller.setAnimation(animation.animationsIds.get(animation.next));
}
animation.controller.update(Gdx.graphics.getDeltaTime());
}
}