Added support for gpu skinning. Added animation system.
This commit is contained in:
@@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -19,6 +19,7 @@ import com.badlogic.gdx.Gdx;
|
|||||||
import com.badlogic.gdx.graphics.Camera;
|
import com.badlogic.gdx.graphics.Camera;
|
||||||
import com.badlogic.gdx.graphics.Color;
|
import com.badlogic.gdx.graphics.Color;
|
||||||
import com.badlogic.gdx.graphics.GL20;
|
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.Renderable;
|
||||||
import com.badlogic.gdx.graphics.g3d.Shader;
|
import com.badlogic.gdx.graphics.g3d.Shader;
|
||||||
import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
|
import com.badlogic.gdx.graphics.g3d.attributes.ColorAttribute;
|
||||||
@@ -30,59 +31,100 @@ import com.badlogic.gdx.math.Vector3;
|
|||||||
import com.badlogic.gdx.utils.GdxRuntimeException;
|
import com.badlogic.gdx.utils.GdxRuntimeException;
|
||||||
|
|
||||||
public class SingleLightPerPixelShader implements Shader{
|
public class SingleLightPerPixelShader implements Shader{
|
||||||
private static final String VERTEX_SHADER_PATH = "shaders/directionalPerPixelSingleLight/directionalPerPixel_vert.glsl";
|
private static final int MAX_NUM_BONES = 4;
|
||||||
private static final String FRAGMENT_SHADER_PATH = "shaders/directionalPerPixelSingleLight/directionalPerPixel_frag.glsl";
|
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 Camera camera;
|
||||||
private RenderContext context;
|
private RenderContext context;
|
||||||
private Matrix4 normalMatrix;
|
private Matrix4 normalMatrix;
|
||||||
|
|
||||||
// Uniform locations.
|
// Uniform locations.
|
||||||
private int u_geomTrans;
|
private int[] u_geomTrans;
|
||||||
private int u_projTrans;
|
private int[] u_projTrans;
|
||||||
private int u_lightPos;
|
private int[] u_lightPos;
|
||||||
private int u_lightDiffuse;
|
private int[] u_lightDiffuse;
|
||||||
private int u_specular;
|
private int[] u_specular;
|
||||||
private int u_ambient;
|
private int[] u_ambient;
|
||||||
private int u_shiny;
|
private int[] u_shiny;
|
||||||
private int u_cameraPos;
|
private int[] u_cameraPos;
|
||||||
private int u_materialDiffuse;
|
private int[] u_materialDiffuse;
|
||||||
private int u_normalMatrix;
|
private int[] u_normalMatrix;
|
||||||
|
private int[] u_bones;
|
||||||
|
|
||||||
public SingleLightPerPixelShader(){
|
public SingleLightPerPixelShader(){
|
||||||
program = null;
|
skinningProgram = null;
|
||||||
camera = null;
|
baseProgram = null;
|
||||||
context = null;
|
camera = null;
|
||||||
|
context = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void init() throws GdxRuntimeException{
|
public void init() throws GdxRuntimeException{
|
||||||
normalMatrix = new Matrix4().idt();
|
normalMatrix = new Matrix4().idt();
|
||||||
|
u_bones = new int[MAX_NUM_BONES];
|
||||||
|
|
||||||
// Compile the shader.
|
// 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())
|
skinningProgram = new ShaderProgram(INCLUDE_SKINNING + vertexCode, fragmentCode);
|
||||||
throw new GdxRuntimeException(program.getLog());
|
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.
|
// Cache uniform locations.
|
||||||
u_projTrans = program.getUniformLocation("u_projTrans");
|
u_projTrans [0] = skinningProgram.getUniformLocation("u_projTrans");
|
||||||
u_geomTrans = program.getUniformLocation("u_geomTrans");
|
u_geomTrans [0] = skinningProgram.getUniformLocation("u_geomTrans");
|
||||||
u_lightPos = program.getUniformLocation("u_lightPos");
|
u_lightPos [0] = skinningProgram.getUniformLocation("u_lightPos");
|
||||||
u_lightDiffuse = program.getUniformLocation("u_lightDiffuse");
|
u_lightDiffuse [0] = skinningProgram.getUniformLocation("u_lightDiffuse");
|
||||||
u_specular = program.getUniformLocation("u_specular");
|
u_specular [0] = skinningProgram.getUniformLocation("u_specular");
|
||||||
u_ambient = program.getUniformLocation("u_ambient");
|
u_ambient [0] = skinningProgram.getUniformLocation("u_ambient");
|
||||||
u_shiny = program.getUniformLocation("u_shiny");
|
u_shiny [0] = skinningProgram.getUniformLocation("u_shiny");
|
||||||
u_cameraPos = program.getUniformLocation("u_cameraPos");
|
u_cameraPos [0] = skinningProgram.getUniformLocation("u_cameraPos");
|
||||||
u_materialDiffuse = program.getUniformLocation("u_materialDiffuse");
|
u_materialDiffuse [0] = skinningProgram.getUniformLocation("u_materialDiffuse");
|
||||||
u_normalMatrix = program.getUniformLocation("u_normalMatrix");
|
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
|
@Override
|
||||||
public void dispose(){
|
public void dispose(){
|
||||||
if(program != null)
|
if(skinningProgram != null) skinningProgram.dispose();
|
||||||
program.dispose();
|
if(baseProgram != null) baseProgram.dispose();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -118,11 +160,6 @@ public class SingleLightPerPixelShader implements Shader{
|
|||||||
|
|
||||||
this.camera = camera;
|
this.camera = camera;
|
||||||
this.context = context;
|
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.
|
// Set render context.
|
||||||
this.context.setDepthTest(GL20.GL_LEQUAL);
|
this.context.setDepthTest(GL20.GL_LEQUAL);
|
||||||
@@ -131,6 +168,10 @@ public class SingleLightPerPixelShader implements Shader{
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(Renderable renderable){
|
public void render(Renderable renderable){
|
||||||
|
ShaderProgram program;
|
||||||
|
int index;
|
||||||
|
boolean bonesEnabled;
|
||||||
|
|
||||||
// Get material colors.
|
// Get material colors.
|
||||||
Vector3 lightPosition = renderable.environment.directionalLights.get(0).direction;
|
Vector3 lightPosition = renderable.environment.directionalLights.get(0).direction;
|
||||||
Color diffuseLightColor = renderable.environment.directionalLights.get(0).color;
|
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;
|
Color ambientColor = ((ColorAttribute)renderable.environment.get(ColorAttribute.AmbientLight)).color;
|
||||||
float shininess = ((FloatAttribute)renderable.material.get(FloatAttribute.Shininess)).value;
|
float shininess = ((FloatAttribute)renderable.material.get(FloatAttribute.Shininess)).value;
|
||||||
|
|
||||||
// Set model dependant uniforms.
|
if(renderable.mesh.getVertexAttribute(VertexAttributes.Usage.BoneWeight) != null){
|
||||||
program.setUniformMatrix(u_geomTrans, renderable.worldTransform);
|
program = skinningProgram;
|
||||||
program.setUniformMatrix(u_normalMatrix, normalMatrix.idt().mul(renderable.worldTransform).inv().tra());
|
index = 0;
|
||||||
program.setUniformf(u_lightPos, lightPosition);
|
bonesEnabled = true;
|
||||||
program.setUniformf(u_lightDiffuse, diffuseLightColor);
|
}else{
|
||||||
program.setUniformf(u_materialDiffuse, diffuseColor);
|
program = baseProgram;
|
||||||
program.setUniformf(u_specular, specularColor);
|
index = 1;
|
||||||
program.setUniformf(u_ambient, ambientColor);
|
bonesEnabled = false;
|
||||||
program.setUniformf(u_shiny, shininess);
|
}
|
||||||
|
|
||||||
|
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);
|
renderable.mesh.render(program, renderable.primitiveType, renderable.meshPartOffset, renderable.meshPartSize);
|
||||||
|
|
||||||
|
program.end();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void end(){
|
public void end(){
|
||||||
program.end();
|
|
||||||
|
|
||||||
this.camera = null;
|
this.camera = null;
|
||||||
this.context = null;
|
this.context = null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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.interfaces.ImageProcessor.MarkerData;
|
||||||
import ve.ucv.ciens.ccg.nxtar.network.monitors.MotorEventQueue;
|
import ve.ucv.ciens.ccg.nxtar.network.monitors.MotorEventQueue;
|
||||||
import ve.ucv.ciens.ccg.nxtar.network.monitors.VideoFrameMonitor;
|
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.MarkerPositioningSystem;
|
||||||
import ve.ucv.ciens.ccg.nxtar.systems.MarkerRenderingSystem;
|
import ve.ucv.ciens.ccg.nxtar.systems.MarkerRenderingSystem;
|
||||||
import ve.ucv.ciens.ccg.nxtar.systems.ObjectRenderingSystem;
|
import ve.ucv.ciens.ccg.nxtar.systems.ObjectRenderingSystem;
|
||||||
@@ -191,14 +192,19 @@ public class InGameState extends BaseState{
|
|||||||
|
|
||||||
// Set up the game world.
|
// Set up the game world.
|
||||||
gameWorld = new World();
|
gameWorld = new World();
|
||||||
|
|
||||||
entityCreator = new MarkerTestEntityCreator();
|
entityCreator = new MarkerTestEntityCreator();
|
||||||
entityCreator.setWorld(gameWorld);
|
entityCreator.setWorld(gameWorld);
|
||||||
entityCreator.createAllEntities();
|
entityCreator.createAllEntities();
|
||||||
|
|
||||||
gameWorld.setSystem(new MarkerPositioningSystem());
|
gameWorld.setSystem(new MarkerPositioningSystem());
|
||||||
|
gameWorld.setSystem(new AnimationSystem());
|
||||||
|
|
||||||
markerRenderingSystem = new MarkerRenderingSystem(modelBatch);
|
markerRenderingSystem = new MarkerRenderingSystem(modelBatch);
|
||||||
objectRenderingSystem = new ObjectRenderingSystem(modelBatch);
|
objectRenderingSystem = new ObjectRenderingSystem(modelBatch);
|
||||||
gameWorld.setSystem(markerRenderingSystem, true);
|
gameWorld.setSystem(markerRenderingSystem, true);
|
||||||
gameWorld.setSystem(objectRenderingSystem, true);
|
gameWorld.setSystem(objectRenderingSystem, true);
|
||||||
|
|
||||||
gameWorld.initialize();
|
gameWorld.initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,23 +15,32 @@
|
|||||||
*/
|
*/
|
||||||
package ve.ucv.ciens.ccg.nxtar.systems;
|
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.Aspect;
|
||||||
|
import com.artemis.ComponentMapper;
|
||||||
import com.artemis.Entity;
|
import com.artemis.Entity;
|
||||||
|
import com.artemis.annotations.Mapper;
|
||||||
import com.artemis.systems.EntityProcessingSystem;
|
import com.artemis.systems.EntityProcessingSystem;
|
||||||
|
import com.badlogic.gdx.Gdx;
|
||||||
|
|
||||||
public class AnimationSystem extends EntityProcessingSystem {
|
public class AnimationSystem extends EntityProcessingSystem {
|
||||||
|
@Mapper ComponentMapper<AnimationComponent> animationMapper;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public AnimationSystem(){
|
public AnimationSystem(){
|
||||||
super(Aspect.getAspectForAll(ModelComponent.class));
|
super(Aspect.getAspectForAll(AnimationComponent.class));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void process(Entity e) {
|
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());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user