#include "gamemath/ArmatureAnimation.h" #include "gamemath/Matrix4x4f.h" #include "gamemath/OrbitCamera.h" #include "gamemath/Scalar.h" #include "renderer/Drawing.h" #include "renderer/Renderable.h" #include "renderer/Renderer.h" #include "renderer/Texture.h" #include "shadercollection/ShaderCollection.h" #include "shadercollection/ShaderConfiguration2DSDF.h" #include "shadercollection/ShaderConfiguration2DTexture.h" #include "shadercollection/ShaderConfiguration3DLit.h" #include "shadercollection/ShaderConfiguration3DLitAnimated.h" #include "shell/Shell.h" #include "shell/ShellCallbacks.h" #include "shell/ShellKeyCodes.h" #include "stem_core.h" #if defined(STEM_PLATFORM_macosx) #include "nsopenglshell/NSOpenGLShell.h" #include "nsopenglshell/NSOpenGLTarget.h" #elif defined(STEM_PLATFORM_iphonesimulator) || defined(STEM_PLATFORM_iphoneos) #include "eaglshell/EAGLShell.h" #include "eaglshell/EAGLTarget.h" #elif defined(STEM_PLATFORM_windows) #include "wglshell/WGLShell.h" #include "wglshell/WGLTarget.h" #elif defined(STEM_PLATFORM_linux) #include "glxshell/GLXShell.h" #include "glxshell/GLXTarget.h" #elif defined(STEM_PLATFORM_android) #include "eglshell/EGLShell.h" #include "eglshell/EGLTarget.h" #else #error Unsupported platform #endif #include #include #include #include #ifdef STEM_PLATFORM_android #include #define printf(format, ...) __android_log_print(ANDROID_LOG_INFO, "Renderer", format, ##__VA_ARGS__); #define fprintf(stderr, format, ...) __android_log_print(ANDROID_LOG_INFO, "Renderer", format, ##__VA_ARGS__); #endif #define PROJECTION_FOV 60.0f #define FBO_WIDTH 200 #define FBO_HEIGHT 150 static Renderer * renderer; static RenderPipelineConfiguration pipelineConfiguration2D; static RenderPipelineConfiguration pipelineConfiguration3D; static RenderLayer * renderLayer2D; static RenderLayer * renderLayer3D; static Texture * checkerboardTexture; static Texture * solidColorTexture; static VertexBuffer * vertexBuffer; static VertexBuffer * armatureVertexBuffer; static Renderable * renderable; static Renderable * armatureRenderable; static Box6f renderableBounds; static Texture * texture; static Texture * textureSDF; static Renderable * sprite; static Armature * armature; static ArmatureAnimation * animation; static ArmaturePose * pose; static OrbitCamera * camera; static ShaderUniformConfiguration perspectiveProjectionUniform; static ShaderUniformConfiguration orthoProjectionUniform; static ShaderUniformConfiguration viewTransformUniform; static ShaderConfiguration3DLit * shaderConfiguration3D; static ShaderConfiguration3DLitAnimated * shaderConfiguration3DAnimated; static ShaderConfiguration3DLitAnimated * shaderConfiguration3DAnimatedArmature; static ShaderConfiguration2DTexture * shaderConfiguration2D; static ShaderConfiguration2DSDF * shaderConfiguration2DSDF; static unsigned int viewWidth = 1280, viewHeight = 720; static float viewRatio = 16.0f / 9.0f; static float scaleFactor = 1.0f; static double animationStartTime, lastAnimationTime; static bool animating; static bool spriteMode; static RenderTarget * renderTarget; static bool useFBO; static int scaleFilter = 0; static float sdfThreshold = 0.5f; static float sdfSmoothRange = 0.0f; static Vector2f spriteOffset; static quadTransformBits spriteTransform; static Color4f clearColor; static bool Target_draw(double referenceTime, double activeDrawDelta) { if (animating && pose != NULL) { ArmaturePose_resetAllPoseBones(pose); ArmatureAnimation_applyPoseAtTime(animation, pose, referenceTime - animationStartTime, 1.0f, ANIMATION_CURVE_SAMPLES_DEFAULT); ArmaturePose_computePoseBoneTransforms(pose, armature); Shell_redisplay(); } if (useFBO) { Renderer_setRenderTarget(renderer, renderTarget); } Renderer_clear(renderer, clearColor); if (spriteMode) { Renderer_drawLayer(renderer, renderLayer2D, referenceTime, activeDrawDelta); } else { ShaderUniformConfiguration_setMat4_Matrix4x4f(&viewTransformUniform, call_virtual(getTransform, camera)); Renderer_drawLayer(renderer, renderLayer3D, referenceTime, activeDrawDelta); } if (useFBO) { Renderer_setRenderTarget(renderer, NULL); Renderer_clear(renderer, clearColor); ShaderConfiguration * fboShaderConfiguration; if (scaleFilter == 0) { fboShaderConfiguration = ShaderCollection_getRenderTargetShaderConfiguration(); Texture_updateOptions(renderTarget->colorTexture, TEXTURE_OPTION_MAGNIFY_NEAREST); } else if (scaleFilter == 1) { fboShaderConfiguration = ShaderCollection_getRenderTargetAdaptiveAreaFilterShaderConfiguration(renderer->viewportWidth, renderer->viewportHeight, renderTarget->width, renderTarget->height); Texture_updateOptions(renderTarget->colorTexture, TEXTURE_OPTION_MAGNIFY_NEAREST); } else if (scaleFilter == 2) { fboShaderConfiguration = ShaderCollection_getRenderTargetBiasedLinearShaderConfiguration(); Texture_updateOptions(renderTarget->colorTexture, 0); } else { fboShaderConfiguration = ShaderCollection_getRenderTargetShaderConfiguration(); Texture_updateOptions(renderTarget->colorTexture, 0); } drawRenderTarget(renderer, renderTarget, fboShaderConfiguration); } return true; } static void updateProjection() { float ratio; if (useFBO) { ratio = (float) FBO_WIDTH / FBO_HEIGHT; } else { ratio = viewRatio; } Matrix4x4f perspectiveMatrix = Matrix4x4f_perspective(MATRIX4x4f_IDENTITY, PROJECTION_FOV, ratio, 0.5f, 100.0f); ShaderUniformConfiguration_setMat4_Matrix4x4f(&perspectiveProjectionUniform, perspectiveMatrix); Matrix4x4f orthoMatrix = Matrix4x4f_ortho(MATRIX4x4f_IDENTITY, -ratio, ratio, -1.0f, 1.0f, -1.0f, 1.0f); ShaderUniformConfiguration_setMat4_Matrix4x4f(&orthoProjectionUniform, orthoMatrix); } static Box6f getVertexDataBounds(const void * vertices, unsigned int vertexCount, VertexFormat * vertexFormat) { Box6f bounds = BOX6f(FLT_MAX, -FLT_MAX, FLT_MAX, -FLT_MAX, FLT_MAX, -FLT_MAX); size_t vertexSize = vertexFormat->bytesPerVertex; for (unsigned int vertexIndex = 0; vertexIndex < vertexCount; vertexIndex++) { Vector3f position = *((Vector3f *) (vertices + vertexIndex * vertexSize)); if (position.x < bounds.xMin) { bounds.xMin = position.x; } if (position.x > bounds.xMax) { bounds.xMax = position.x; } if (position.y < bounds.yMin) { bounds.yMin = position.y; } if (position.y > bounds.yMax) { bounds.yMax = position.y; } if (position.z < bounds.zMin) { bounds.zMin = position.z; } if (position.z > bounds.zMax) { bounds.zMax = position.z; } } return bounds; } static void initScene1() { struct vertex_p3f_t2f_n3f_c4f vertices[] = { {{-1.0f, -1.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, {{1.0f, -1.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}}, {{-1.0f, 1.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}} }; uint32_t indexes[] = { 0, 1, 2 }; RenderLayer_removeAllRenderables(renderLayer3D); clearColor = COLOR4f(0.0f, 0.125f, 0.25f, 0.0f); call_virtual(setLights, shaderConfiguration3D, VECTOR3f(0.0f, 8.0f, 8.0f), COLOR3f(1.0f, 1.0f, 0.95f), VECTOR3f(-1.0f, -2.0f, -8.0f), COLOR3f(0.8f, 0.8f, 0.8f), V3f(0.0f, -1.0f, 0.0f), C3f(0.11f, 0.11f, 0.1f), COLOR3f(0.1f, 0.1f, 0.105f)); if (sprite != NULL) { Renderable_dispose(sprite); sprite = NULL; } spriteMode = false; if (renderable != NULL) { Renderable_dispose(renderable); } if (vertexBuffer != NULL) { VertexBuffer_dispose(vertexBuffer); } vertexBuffer = VertexBuffer_create(shaderConfiguration3D->shader->vertexFormat, vertices, sizeof_count(vertices), indexes, sizeof_count(indexes), BUFFER_USAGE_STATIC); renderable = Renderable_createWithVertexBuffer(PRIMITIVE_TRIANGLES, &pipelineConfiguration3D, shaderConfiguration3D, vertexBuffer, false, NULL, NULL); renderableBounds = getVertexDataBounds(vertices, sizeof_count(vertices), vertexBuffer->vertexFormat); RenderLayer_addRenderable(renderLayer3D, renderable, 0, RECT4i_EMPTY); if (camera != NULL) { OrbitCamera_dispose(camera); } camera = OrbitCamera_create(); } static VertexBuffer * createArmatureDebugVertexBuffer(Armature * self, VertexFormat * vertexFormat) { struct vertex_p3f_t2f_n3f_c4f_b4f_w4f boneVertices[] = { {{ 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f}, {-0.7071067811865476f, -0.7071067811865476f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{-0.1f, 0.1f, 0.1f}, {0.0f, 0.0f}, {-0.7071067811865476f, -0.7071067811865476f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{-0.1f, 0.1f, -0.1f}, {0.0f, 0.0f}, {-0.7071067811865476f, -0.7071067811865476f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{ 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, -0.7071067811865476f, -0.7071067811865476f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{-0.1f, 0.1f, -0.1f}, {0.0f, 0.0f}, {0.0f, -0.7071067811865476f, -0.7071067811865476f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{ 0.1f, 0.1f, -0.1f}, {0.0f, 0.0f}, {0.0f, -0.7071067811865476f, -0.7071067811865476f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{ 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f}, {0.7071067811865476f, -0.7071067811865476f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{ 0.1f, 0.1f, -0.1f}, {0.0f, 0.0f}, {0.7071067811865476f, -0.7071067811865476f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{ 0.1f, 0.1f, 0.1f}, {0.0f, 0.0f}, {0.7071067811865476f, -0.7071067811865476f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{ 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, -0.7071067811865476f, 0.7071067811865476f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{ 0.1f, 0.1f, 0.1f}, {0.0f, 0.0f}, {0.0f, -0.7071067811865476f, 0.7071067811865476f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{-0.1f, 0.1f, 0.1f}, {0.0f, 0.0f}, {0.0f, -0.7071067811865476f, 0.7071067811865476f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{ 0.0f, 1.0f, 0.0f}, {0.0f, 0.0f}, {-0.9938837346736188f, -0.11043152607484653f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{-0.1f, 0.1f, -0.1f}, {0.0f, 0.0f}, {-0.9938837346736188f, -0.11043152607484653f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{-0.1f, 0.1f, 0.1f}, {0.0f, 0.0f}, {-0.9938837346736188f, -0.11043152607484653f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{ 0.0f, 1.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, -0.11043152607484653f, -0.9938837346736188f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{ 0.1f, 0.1f, -0.1f}, {0.0f, 0.0f}, {0.0f, -0.11043152607484653f, -0.9938837346736188f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{-0.1f, 0.1f, -0.1f}, {0.0f, 0.0f}, {0.0f, -0.11043152607484653f, -0.9938837346736188f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{ 0.0f, 1.0f, 0.0f}, {0.0f, 0.0f}, {0.9938837346736188f, -0.11043152607484653f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{ 0.1f, 0.1f, 0.1f}, {0.0f, 0.0f}, {0.9938837346736188f, -0.11043152607484653f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{ 0.1f, 0.1f, -0.1f}, {0.0f, 0.0f}, {0.9938837346736188f, -0.11043152607484653f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{ 0.0f, 1.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, -0.11043152607484653f, 0.9938837346736188f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{-0.1f, 0.1f, 0.1f}, {0.0f, 0.0f}, {0.0f, -0.11043152607484653f, 0.9938837346736188f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{ 0.1f, 0.1f, 0.1f}, {0.0f, 0.0f}, {0.0f, -0.11043152607484653f, 0.9938837346736188f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}} }; uint32_t boneIndexes[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 }; struct vertex_p3f_t2f_n3f_c4f_b4f_w4f * vertices = malloc(sizeof(boneVertices) * self->boneCount); uint32_t * indexes = malloc(sizeof(boneIndexes) * self->boneCount); size_t boneVertexCount = sizeof_count(boneVertices); size_t boneIndexCount = sizeof_count(boneIndexes); for (unsigned int boneIndex = 0; boneIndex < self->boneCount; boneIndex++) { Vector3f boneVector = Vector3f_subtract(self->bones[boneIndex].endpoint, self->bones[boneIndex].position); float boneLength = Vector3f_magnitude(boneVector); Vector3f_normalize(&boneVector); float boneDotUp = Vector3f_dot(boneVector, VECTOR3f_UP); Vector3f axis; float angle; if (boneDotUp < -0.9999f) { axis = VECTOR3f_RIGHT; angle = M_PI; } else if (boneDotUp > 0.9999f) { axis = VECTOR3f_RIGHT; angle = 0.0f; } else { axis = Vector3f_normalized(Vector3f_cross(boneVector, VECTOR3f_UP)); angle = -acosf(boneDotUp); } Matrix4x4f matrix = MATRIX4x4f_IDENTITY; Matrix4x4f_translate(&matrix, self->bones[boneIndex].position.x, self->bones[boneIndex].position.y, self->bones[boneIndex].position.z); Matrix4x4f_scale(&matrix, boneLength, boneLength, boneLength); Matrix4x4f_rotate(&matrix, axis, angle); for (unsigned int vertexIndex = 0; vertexIndex < boneVertexCount; vertexIndex++) { struct vertex_p3f_t2f_n3f_c4f_b4f_w4f vertex = boneVertices[vertexIndex]; vertex.boneIndexes[0] = boneIndex; Vector3f position = Matrix4x4f_multiplyVector3f(matrix, VECTOR3f(vertex.position[0], vertex.position[1], vertex.position[2])); Vector3f normal = Matrix4x4f_multiplyVector3f_rotationOnly(matrix, VECTOR3f(vertex.normal[0], vertex.normal[1], vertex.normal[2])); vertex.position[0] = position.x; vertex.position[1] = position.y; vertex.position[2] = position.z; vertex.normal[0] = normal.x; vertex.normal[1] = normal.y; vertex.normal[2] = normal.z; vertices[boneIndex * boneVertexCount + vertexIndex] = vertex; } for (unsigned int indexIndex = 0; indexIndex < boneIndexCount; indexIndex++) { indexes[boneIndex * boneIndexCount + indexIndex] = boneIndexes[indexIndex] + boneIndex * boneIndexCount; } } VertexBuffer * vertexBuffer = VertexBuffer_create(vertexFormat, vertices, sizeof_count(boneVertices) * self->boneCount, indexes, sizeof_count(boneIndexes) * self->boneCount, BUFFER_USAGE_STATIC); free(vertices); free(indexes); return vertexBuffer; } static void initScene2() { struct vertex_p3f_t2f_n3f_c4f_b4f_w4f vertices[] = { {{0.0f, -1.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {1, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{-1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{1.0f, 0.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{0.0f, 1.0f, 0.0f}, {0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {2, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}} }; uint32_t indexes[] = { 0, 2, 1, 1, 2, 3 }; ArmatureBone bones[] = { {0, BONE_ID_NONE, VECTOR3f(0.0f, 0.0f, 0.0f), VECTOR3f(1.0f, 0.0f, 0.0f), QUATERNIONf_IDENTITY, BONE_INDEX_NOT_FOUND}, {1, 0, VECTOR3f(0.0f, -1.0f, 0.0f), VECTOR3f(1.0f, -1.0f, 0.0f), QUATERNIONf_IDENTITY, 0}, {2, 0, VECTOR3f(0.0f, 1.0f, 0.0f), VECTOR3f(1.0f, 1.0f, 0.0f), QUATERNIONf_IDENTITY, 0} }; ArmatureAnimationBoneKeyframe frame1Bones[] = { {1, {-1.0f, 0.0f, 0.0f}, {0.5f, 1.0f}, {0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}, QUATERNIONf_IDENTITY, {1.0f, 0.0f}, {0.0f, 0.0f}}, {2, {1.0f, 0.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}, QUATERNIONf_IDENTITY, {1.0f, 0.0f}, {0.0f, 0.0f}} }; ArmatureAnimationBoneKeyframe frame2Bones[] = { {1, {1.0f, 0.0f, 0.0f}, {0.5f, 1.0f}, {0.5f, 0.0f}, {1.0f, 1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 0.0f}, QUATERNIONf_IDENTITY, {1.0f, 0.0f}, {0.0f, 0.0f}}, {2, {-1.0f, 0.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 0.0f}, QUATERNIONf_IDENTITY, {1.0f, 0.0f}, {0.0f, 0.0f}} }; ArmatureAnimationKeyframe keyframes[] = { {1.0f, sizeof_count(frame1Bones), frame1Bones}, {0.5f, sizeof_count(frame2Bones), frame2Bones} }; RenderLayer_removeAllRenderables(renderLayer3D); clearColor = COLOR4f(0.25f, 0.0f, 0.125f, 0.0f); call_virtual(setLights, shaderConfiguration3DAnimated, VECTOR3f(0.0f, 8.0f, 8.0f), COLOR3f(1.0f, 1.0f, 0.95f), VECTOR3f(-1.0f, -2.0f, -8.0f), COLOR3f(0.8f, 0.8f, 0.8f), V3f(0.0f, -1.0f, 0.0f), C3f(0.11f, 0.11f, 0.1f), COLOR3f(0.1f, 0.1f, 0.105f)); if (sprite != NULL) { Renderable_dispose(sprite); sprite = NULL; } spriteMode = false; if (armature != NULL) { Armature_dispose(armature); } if (animation != NULL) { ArmatureAnimation_dispose(animation); } if (pose != NULL) { ArmaturePose_dispose(pose); } if (vertexBuffer != NULL) { VertexBuffer_dispose(vertexBuffer); } if (renderable != NULL) { Renderable_dispose(renderable); } armature = Armature_create(sizeof_count(bones), bones); animation = ArmatureAnimation_create(true, sizeof_count(keyframes), keyframes, 0, NULL); pose = ArmaturePose_createWithArmature(armature); ArmatureAnimation_applyPoseAtTime(animation, pose, 0.0, 1.0f, ANIMATION_CURVE_SAMPLES_DEFAULT); shaderConfiguration3DAnimated->pose = pose; shaderConfiguration3DAnimatedArmature->pose = pose; vertexBuffer = VertexBuffer_create(shaderConfiguration3DAnimated->shader->vertexFormat, vertices, sizeof_count(vertices), indexes, sizeof_count(indexes), BUFFER_USAGE_STATIC); renderable = Renderable_createWithVertexBuffer(PRIMITIVE_TRIANGLES, &pipelineConfiguration3D, shaderConfiguration3DAnimated, vertexBuffer, false, NULL, NULL); renderableBounds = getVertexDataBounds(vertices, sizeof_count(vertices), vertexBuffer->vertexFormat); RenderLayer_addRenderable(renderLayer3D, renderable, 0, RECT4i_EMPTY); if (armatureVertexBuffer != NULL ){ VertexBuffer_dispose(armatureVertexBuffer); } if (armatureRenderable != NULL) { Renderable_dispose(armatureRenderable); } armatureVertexBuffer = createArmatureDebugVertexBuffer(armature, shaderConfiguration3DAnimated->shader->vertexFormat); armatureRenderable = Renderable_createWithVertexBuffer(PRIMITIVE_TRIANGLES, &pipelineConfiguration3D, shaderConfiguration3DAnimated, armatureVertexBuffer, false, NULL, NULL); armatureRenderable->visible = false; RenderLayer_addRenderable(renderLayer3D, armatureRenderable, 0, RECT4i_EMPTY); if (camera != NULL) { OrbitCamera_dispose(camera); } camera = OrbitCamera_create(); animationStartTime = Shell_getCurrentTime(); animating = true; } static void initScene3() { struct vertex_p3f_t2f_n3f_c4f_b4f_w4f vertices[] = { {{-1.0f, -4.0f, -1.0f}, {1.0f, 0.0f}, {0.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{1.0f, -4.0f, -1.0f}, {0.0f, 0.0f}, {0.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{1.0f, -4.0f, 1.0f}, {0.0f, 1.0f}, {0.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{-1.0f, -4.0f, 1.0f}, {1.0f, 1.0f}, {0.0f, -1.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{-1.0f, -4.0f, 1.0f}, {0.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{-1.0f, -2.0f, 1.0f}, {0.0f, 1.0f}, {-1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{-1.0f, -2.0f, -1.0f}, {1.0f, 1.0f}, {-1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{-1.0f, -4.0f, -1.0f}, {1.0f, 0.0f}, {-1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{-1.0f, -4.0f, -1.0f}, {0.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{-1.0f, -2.0f, -1.0f}, {0.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{1.0f, -2.0f, -1.0f}, {1.0f, 1.0f}, {0.0f, 0.0f, -1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{1.0f, -4.0f, -1.0f}, {1.0f, 0.0f}, {0.0f, 0.0f, -1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{1.0f, -4.0f, -1.0f}, {0.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{1.0f, -2.0f, -1.0f}, {0.0f, 1.0f}, {1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{1.0f, -2.0f, 1.0f}, {1.0f, 1.0f}, {1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{1.0f, -4.0f, 1.0f}, {1.0f, 0.0f}, {1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{1.0f, -4.0f, 1.0f}, {0.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{1.0f, -2.0f, 1.0f}, {0.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{-1.0f, -2.0f, 1.0f}, {1.0f, 1.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{-1.0f, -4.0f, 1.0f}, {1.0f, 0.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 0, 0}, {1.0f, 0.0f, 0.0f, 0.0f}}, {{-1.0f, -1.0f, 1.0f}, {0.0f, 1.5f}, {-1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 0, 0}, {0.5f, 0.5f, 0.0f, 0.0f}}, {{-1.0f, 0.0f, 1.0f}, {0.0f, 2.0f}, {-1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 0, 0}, {0.0f, 1.0f, 0.0f, 0.0f}}, {{-1.0f, 0.0f, -1.0f}, {1.0f, 2.0f}, {-1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 0, 0}, {0.0f, 1.0f, 0.0f, 0.0f}}, {{-1.0f, -1.0f, -1.0f}, {1.0f, 1.5f}, {-1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 0, 0}, {0.5f, 0.5f, 0.0f, 0.0f}}, {{-1.0f, -1.0f, -1.0f}, {0.0f, 1.5f}, {0.0f, 0.0f, -1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 0, 0}, {0.5f, 0.5f, 0.0f, 0.0f}}, {{-1.0f, 0.0f, -1.0f}, {0.0f, 2.0f}, {0.0f, 0.0f, -1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 0, 0}, {0.0f, 1.0f, 0.0f, 0.0f}}, {{1.0f, 0.0f, -1.0f}, {1.0f, 2.0f}, {0.0f, 0.0f, -1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 0, 0}, {0.0f, 1.0f, 0.0f, 0.0f}}, {{1.0f, -1.0f, -1.0f}, {1.0f, 1.5f}, {0.0f, 0.0f, -1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 0, 0}, {0.5f, 0.5f, 0.0f, 0.0f}}, {{1.0f, -1.0f, -1.0f}, {0.0f, 1.5f}, {1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 0, 0}, {0.5f, 0.5f, 0.0f, 0.0f}}, {{1.0f, 0.0f, -1.0f}, {0.0f, 2.0f}, {1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 0, 0}, {0.0f, 1.0f, 0.0f, 0.0f}}, {{1.0f, 0.0f, 1.0f}, {1.0f, 2.0f}, {1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 0, 0}, {0.0f, 1.0f, 0.0f, 0.0f}}, {{1.0f, -1.0f, 1.0f}, {1.0f, 1.5f}, {1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 0, 0}, {0.5f, 0.5f, 0.0f, 0.0f}}, {{1.0f, -1.0f, 1.0f}, {0.0f, 1.5f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 0, 0}, {0.5f, 0.5f, 0.0f, 0.0f}}, {{1.0f, 0.0f, 1.0f}, {0.0f, 2.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 0, 0}, {0.0f, 1.0f, 0.0f, 0.0f}}, {{-1.0f, 0.0f, 1.0f}, {1.0f, 2.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 0, 0}, {0.0f, 1.0f, 0.0f, 0.0f}}, {{-1.0f, -1.0f, 1.0f}, {1.0f, 1.5f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 0, 0}, {0.5f, 0.5f, 0.0f, 0.0f}}, {{-1.0f, 2.0f, 1.0f}, {0.0f, 3.0f}, {-1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 2, 0}, {0.0f, 0.5f, 0.5f, 0.0f}}, {{-1.0f, 4.0f, 1.0f}, {0.0f, 4.0f}, {-1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 2, 0}, {0.0f, 0.0f, 1.0f, 0.0f}}, {{-1.0f, 4.0f, -1.0f}, {1.0f, 4.0f}, {-1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 2, 0}, {0.0f, 0.0f, 1.0f, 0.0f}}, {{-1.0f, 2.0f, -1.0f}, {1.0f, 3.0f}, {-1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 2, 0}, {0.0f, 0.5f, 0.5f, 0.0f}}, {{-1.0f, 2.0f, -1.0f}, {0.0f, 3.0f}, {0.0f, 0.0f, -1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 2, 0}, {0.0f, 0.5f, 0.5f, 0.0f}}, {{-1.0f, 4.0f, -1.0f}, {0.0f, 4.0f}, {0.0f, 0.0f, -1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 2, 0}, {0.0f, 0.0f, 1.0f, 0.0f}}, {{1.0f, 4.0f, -1.0f}, {1.0f, 4.0f}, {0.0f, 0.0f, -1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 2, 0}, {0.0f, 0.0f, 1.0f, 0.0f}}, {{1.0f, 2.0f, -1.0f}, {1.0f, 3.0f}, {0.0f, 0.0f, -1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 2, 0}, {0.0f, 0.5f, 0.5f, 0.0f}}, {{1.0f, 2.0f, -1.0f}, {0.0f, 3.0f}, {1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 2, 0}, {0.0f, 0.5f, 0.5f, 0.0f}}, {{1.0f, 4.0f, -1.0f}, {0.0f, 4.0f}, {1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 2, 0}, {0.0f, 0.0f, 1.0f, 0.0f}}, {{1.0f, 4.0f, 1.0f}, {1.0f, 4.0f}, {1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 2, 0}, {0.0f, 0.0f, 1.0f, 0.0f}}, {{1.0f, 2.0f, 1.0f}, {1.0f, 3.0f}, {1.0f, 0.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 2, 0}, {0.0f, 0.5f, 0.5f, 0.0f}}, {{1.0f, 2.0f, 1.0f}, {0.0f, 3.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 2, 0}, {0.0f, 0.5f, 0.5f, 0.0f}}, {{1.0f, 4.0f, 1.0f}, {0.0f, 4.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 2, 0}, {0.0f, 0.0f, 1.0f, 0.0f}}, {{-1.0f, 4.0f, 1.0f}, {1.0f, 4.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 0, 2, 0}, {0.0f, 0.0f, 1.0f, 0.0f}}, {{-1.0f, 2.0f, 1.0f}, {1.0f, 3.0f}, {0.0f, 0.0f, 1.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 2, 0}, {0.0f, 0.5f, 0.5f, 0.0f}}, {{1.0f, 4.0f, -1.0f}, {1.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 2, 0}, {0.0f, 0.0f, 1.0f, 0.0f}}, {{-1.0f, 4.0f, -1.0f}, {0.0f, 0.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 2, 0}, {0.0f, 0.0f, 1.0f, 0.0f}}, {{-1.0f, 4.0f, 1.0f}, {0.0f, 1.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 2, 0}, {0.0f, 0.0f, 1.0f, 0.0f}}, {{1.0f, 4.0f, 1.0f}, {1.0f, 1.0f}, {0.0f, 1.0f, 0.0f}, {1.0f, 1.0f, 1.0f, 1.0f}, {0, 1, 2, 0}, {0.0f, 0.0f, 1.0f, 0.0f}} }; uint32_t indexes[] = { 0, 1, 2, 2, 3, 0, 4, 5, 6, 6, 7, 4, 8, 9, 10, 10, 11, 8, 12, 13, 14, 14, 15, 12, 16, 17, 18, 18, 19, 16, 5, 20, 23, 23, 6, 5, 9, 24, 27, 27, 10, 9, 13, 28, 31, 31, 14, 13, 17, 32, 35, 35, 18, 17, 20, 21, 22, 22, 23, 20, 24, 25, 26, 26, 27, 24, 28, 29, 30, 30, 31, 28, 32, 33, 34, 34, 35, 32, 21, 36, 39, 39, 22, 21, 25, 40, 43, 43, 26, 25, 29, 44, 47, 47, 30, 29, 33, 48, 51, 51, 34, 33, 36, 37, 38, 38, 39, 36, 40, 41, 42, 42, 43, 40, 44, 45, 46, 46, 47, 44, 48, 49, 50, 50, 51, 48, 52, 53, 54, 54, 55, 52 }; ArmatureBone bones[] = { {0, BONE_ID_NONE, VECTOR3f(0.0f, -4.0f, 0.0f), VECTOR3f(0.0f, -1.0f, 0.0f), QUATERNIONf_IDENTITY, BONE_INDEX_NOT_FOUND}, {1, 0, VECTOR3f(0.0f, -1.0f, 0.0f), VECTOR3f(0.0f, 2.0f, 0.0f), QUATERNIONf_IDENTITY, 0}, {2, 1, VECTOR3f(0.0f, 2.0f, 0.0f), VECTOR3f(0.0f, 4.0f, 0.0f), Quaternionf_fromAxisAngle(VECTOR3f(0.0f, 1.0f, 0.0f), M_PI * 0.5), 1} }; ArmatureAnimationBoneKeyframe frame1Bones[] = { {1, {0.0f, 0.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}, QUATERNIONf_IDENTITY, {0.5f, 1.0f}, {0.5f, 0.0f}}, {2, {0.0f, 0.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}, QUATERNIONf_IDENTITY, {0.5f, 1.0f}, {0.5f, 0.0f}} }; ArmatureAnimationBoneKeyframe frame2Bones[] = { {1, {0.0f, 0.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}, Quaternionf_fromAxisAngle(VECTOR3f(0.0f, 0.0f, 1.0f), M_PI * 0.25f), {0.5f, 1.0f}, {0.5f, 0.0f}}, {2, {0.0f, 0.0f, 0.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}, {1.0f, 1.0f, 1.0f}, {1.0f, 1.0f}, {0.0f, 0.0f}, Quaternionf_fromAxisAngle(VECTOR3f(0.0f, 0.0f, 1.0f), M_PI * 0.25f), {0.5f, 1.0f}, {0.5f, 0.0f}} }; ArmatureAnimationKeyframe keyframes[] = { {0.5f, sizeof_count(frame1Bones), frame1Bones}, {0.5f, sizeof_count(frame2Bones), frame2Bones} }; RenderLayer_removeAllRenderables(renderLayer3D); clearColor = COLOR4f(0.125f, 0.0625f, 0.0f, 0.0f); call_virtual(setLights, shaderConfiguration3DAnimated, VECTOR3f(2.0f, 8.0f, 8.0f), COLOR3f(1.0f, 1.0f, 0.95f), VECTOR3f(-3.0f, -2.0f, -8.0f), COLOR3f(0.8f, 0.8f, 0.8f), V3f(0.0f, -1.0f, 0.0f), C3f(0.11f, 0.11f, 0.1f), COLOR3f(0.1f, 0.1f, 0.105f)); if (sprite != NULL) { Renderable_dispose(sprite); sprite = NULL; } spriteMode = false; if (armature != NULL) { Armature_dispose(armature); } if (animation != NULL) { ArmatureAnimation_dispose(animation); } if (pose != NULL) { ArmaturePose_dispose(pose); } if (vertexBuffer != NULL) { VertexBuffer_dispose(vertexBuffer); } if (renderable != NULL) { Renderable_dispose(renderable); } armature = Armature_create(sizeof_count(bones), bones); animation = ArmatureAnimation_create(true, sizeof_count(keyframes), keyframes, 0, NULL); pose = ArmaturePose_createWithArmature(armature); ArmatureAnimation_applyPoseAtTime(animation, pose, 0.0, 1.0f, ANIMATION_CURVE_SAMPLES_DEFAULT); shaderConfiguration3DAnimated->pose = pose; shaderConfiguration3DAnimatedArmature->pose = pose; vertexBuffer = VertexBuffer_create(shaderConfiguration3DAnimated->shader->vertexFormat, vertices, sizeof_count(vertices), indexes, sizeof_count(indexes), BUFFER_USAGE_STATIC); renderable = Renderable_createWithVertexBuffer(PRIMITIVE_TRIANGLES, &pipelineConfiguration3D, shaderConfiguration3DAnimated, vertexBuffer, false, NULL, NULL); renderableBounds = getVertexDataBounds(vertices, sizeof_count(vertices), vertexBuffer->vertexFormat); RenderLayer_addRenderable(renderLayer3D, renderable, 0, RECT4i_EMPTY); if (armatureVertexBuffer != NULL ){ VertexBuffer_dispose(armatureVertexBuffer); } if (armatureRenderable != NULL) { Renderable_dispose(armatureRenderable); } armatureVertexBuffer = createArmatureDebugVertexBuffer(armature, shaderConfiguration3DAnimated->shader->vertexFormat); armatureRenderable = Renderable_createWithVertexBuffer(PRIMITIVE_TRIANGLES, &pipelineConfiguration3D, shaderConfiguration3DAnimated, armatureVertexBuffer, false, NULL, NULL); armatureRenderable->visible = false; RenderLayer_addRenderable(renderLayer3D, armatureRenderable, 0, RECT4i_EMPTY); if (camera != NULL) { OrbitCamera_dispose(camera); } camera = OrbitCamera_create(); camera->cameraDistance = 10.0f; animationStartTime = Shell_getCurrentTime(); animating = true; } static void writeSpriteVertices(Renderable * renderable, VertexIO * vertexIO, void * context) { writeQuad2DMultitextureWithTransform(Rect4f_fromPositionSizeOrigin(spriteOffset, VECTOR2f(1.0f, 1.0f), VECTOR2f(0.5f, 0.5f)), RECT4f(0.0f, 1.0f, 0.0f, 1.0f), COLOR4f(1.0f, 1.0f, 1.0f, 1.0f), 0, spriteTransform, vertexIO); } static void initScene4() { RenderLayer_removeAllRenderables(renderLayer2D); clearColor = COLOR4f(0.0f, 0.125f, 0.0f, 0.0f); if (renderable != NULL) { Renderable_dispose(renderable); renderable = NULL; } if (vertexBuffer != NULL) { VertexBuffer_dispose(vertexBuffer); vertexBuffer = NULL; } if (sprite != NULL) { Renderable_dispose(sprite); } spriteMode = true; spriteOffset = VECTOR2f_ZERO; sprite = Renderable_createWithCallback(PRIMITIVE_TRIANGLES, &pipelineConfiguration2D, shaderConfiguration2D, writeSpriteVertices, NULL, NULL); RenderLayer_addRenderable(renderLayer2D, sprite, 0, RECT4i_EMPTY); } static void initScene5() { RenderLayer_removeAllRenderables(renderLayer2D); clearColor = COLOR4f(0.0f, 0.0f, 0.125f, 0.0f); if (renderable != NULL) { Renderable_dispose(renderable); renderable = NULL; } if (vertexBuffer != NULL) { VertexBuffer_dispose(vertexBuffer); vertexBuffer = NULL; } if (sprite != NULL) { Renderable_dispose(sprite); } spriteMode = true; spriteOffset = VECTOR2f_ZERO; sprite = Renderable_createWithCallback(PRIMITIVE_TRIANGLES, &pipelineConfiguration2D, shaderConfiguration2DSDF, writeSpriteVertices, NULL, NULL); RenderLayer_addRenderable(renderLayer2D, sprite, 0, RECT4i_EMPTY); } static void Target_keyDown(unsigned int charCode, unsigned int keyCode, unsigned int modifiers, bool isRepeat, double referenceTime) { switch (keyCode) { case KEY_CODE_1: initScene1(); Shell_redisplay(); break; case KEY_CODE_2: initScene2(); Shell_redisplay(); break; case KEY_CODE_3: initScene3(); Shell_redisplay(); break; case KEY_CODE_4: initScene4(); Shell_redisplay(); break; case KEY_CODE_5: initScene5(); Shell_redisplay(); break; case KEY_CODE_TAB: if (armatureRenderable != NULL) { armatureRenderable->visible = !armatureRenderable->visible; renderable->visible = !renderable->visible; Shell_redisplay(); } break; case KEY_CODE_A: if (animating) { animating = false; lastAnimationTime = Shell_getCurrentTime(); } else { animating = true; animationStartTime += Shell_getCurrentTime() - lastAnimationTime; Shell_redisplay(); } break; case KEY_CODE_F: if (renderable != NULL) { OrbitCamera_frameBoundingBox(camera, renderableBounds, PROJECTION_FOV, viewRatio); Shell_redisplay(); } break; case KEY_CODE_T: useFBO = !useFBO; updateProjection(); Shell_redisplay(); break; case KEY_CODE_Y: scaleFilter = (scaleFilter + 1) % 4; Shell_redisplay(); break; case KEY_CODE_H: if (sprite != NULL) { spriteTransform ^= QUAD_TRANSFORM_FLIP_X; Shell_redisplay(); } break; case KEY_CODE_V: if (sprite != NULL) { spriteTransform ^= QUAD_TRANSFORM_FLIP_Y; Shell_redisplay(); } break; case KEY_CODE_Q: if (modifiers & MODIFIER_PLATFORM_MENU_COMMAND_BIT) { exit(EXIT_SUCCESS); } if (sprite != NULL) { spriteTransform ^= QUAD_TRANSFORM_ROTATE_CCW; Shell_redisplay(); } break; case KEY_CODE_W: if (sprite != NULL) { spriteTransform ^= QUAD_TRANSFORM_ROTATE_CW; Shell_redisplay(); } break; } } static void Target_keyUp(unsigned int keyCode, unsigned int modifiers, double referenceTime) { } static void Target_keyModifiersChanged(unsigned int modifiers, unsigned int lastModifiers, double referenceTime) { } static void Target_mouseDown(unsigned int buttonNumber, unsigned int buttonMask, float x, float y, unsigned int modifierFlags, double referenceTime) { #ifdef STEM_PLATFORM_android if (y > 1000) { static unsigned int sceneNumber; sceneNumber = (sceneNumber + 1) % 5; switch (sceneNumber) { case 0: initScene1(); Shell_redisplay(); break; case 1: initScene2(); Shell_redisplay(); break; case 2: initScene3(); Shell_redisplay(); break; case 3: initScene4(); Shell_redisplay(); break; case 4: initScene5(); Shell_redisplay(); break; } } else if (y < 200) { useFBO = !useFBO; updateProjection(); Shell_redisplay(); } #endif Shell_setMouseDeltaMode(true); } static void Target_mouseUp(unsigned int buttonNumber, unsigned int buttonMask, float x, float y, unsigned int modifierFlags, double referenceTime) { Shell_setMouseDeltaMode(false); } static void Target_mouseMoved(float x, float y, float deltaX, float deltaY, unsigned int modifierFlags, double referenceTime) { } #define SPRITE_DRAG_RATIO 0.003125f #define THRESHOLD_DRAG_RATIO 0.000625f #define SMOOTH_RANGE_DRAG_RATIO 0.0000625f static void Target_mouseDragged(unsigned int buttonMask, float x, float y, float deltaX, float deltaY, unsigned int modifierFlags, double referenceTime) { deltaX /= scaleFactor; deltaY /= scaleFactor; if (spriteMode) { if (modifierFlags & MODIFIER_SHIFT_BIT) { sdfThreshold = clampf(sdfThreshold + deltaY * THRESHOLD_DRAG_RATIO, 0.0f, 1.0f); ShaderConfiguration2DSDF_setThreshold(shaderConfiguration2DSDF, sdfThreshold); } else if (modifierFlags & MODIFIER_CONTROL_BIT) { sdfSmoothRange = clampf(sdfSmoothRange - deltaY * SMOOTH_RANGE_DRAG_RATIO, 0.0f, 1.0f); ShaderConfiguration2DSDF_setSmoothRange(shaderConfiguration2DSDF, sdfSmoothRange); } else { spriteOffset.x += deltaX * SPRITE_DRAG_RATIO; spriteOffset.y -= deltaY * SPRITE_DRAG_RATIO; } } else { if (modifierFlags & MODIFIER_SHIFT_BIT) { if (modifierFlags & MODIFIER_CONTROL_BIT) { OrbitCamera_offset(camera, 0.0f, 0.0f, deltaY); } else { OrbitCamera_offset(camera, -deltaX, deltaY, 0.0f); } } else if (modifierFlags & MODIFIER_CONTROL_BIT) { OrbitCamera_zoom(camera, deltaY); } else { OrbitCamera_rotate(camera, deltaX, deltaY); } } Shell_redisplay(); } static void Target_resized(unsigned int newWidth, unsigned int newHeight, double referenceTime) { viewWidth = newWidth; viewHeight = newHeight; viewRatio = (float) newWidth / newHeight; if (renderer != NULL) { Renderer_setViewport(renderer, 0, 0, viewWidth, viewHeight, NULL); updateProjection(); } } static void Target_backgrounded(double referenceTime) { } static void Target_foregrounded(double referenceTime) { } static void registerShellCallbacks() { Shell_drawFunc(Target_draw); Shell_resizeFunc(Target_resized); Shell_keyDownFunc(Target_keyDown); Shell_keyUpFunc(Target_keyUp); Shell_keyModifiersChangedFunc(Target_keyModifiersChanged); Shell_mouseDownFunc(Target_mouseDown); Shell_mouseUpFunc(Target_mouseUp); Shell_mouseMovedFunc(Target_mouseMoved); Shell_mouseDraggedFunc(Target_mouseDragged); Shell_backgroundedFunc(Target_backgrounded); Shell_foregroundedFunc(Target_foregrounded); } #if defined(STEM_PLATFORM_macosx) void NSOpenGLTarget_configure(int argc, const char ** argv, struct NSOpenGLShellConfiguration * configuration) { configuration->windowTitle = "Renderer"; configuration->useGLCoreProfile = true; configuration->displayMode.depthBuffer = true; #elif defined(STEM_PLATFORM_iphonesimulator) || defined(STEM_PLATFORM_iphoneos) void EAGLTarget_configure(int argc, char ** argv, struct EAGLShellConfiguration * configuration) { configuration->displayMode.depthAttachment = true; configuration->displayMode.depthPrecision = 24; #elif defined(STEM_PLATFORM_windows) void WGLTarget_configure(void * instance, void * prevInstance, char * commandLine, int command, int argc, const char ** argv, struct WGLShellConfiguration * configuration) { configuration->windowTitle = "Renderer"; configuration->useGLCoreProfile = true; configuration->displayMode.depthBuffer = true; #elif defined(STEM_PLATFORM_linux) void GLXTarget_configure(int argc, const char ** argv, struct GLXShellConfiguration * configuration) { #include "IconData_stemapp.h" configuration->icon.data = STATIC_iconData_stemapp; configuration->icon.size = sizeof_count(STATIC_iconData_stemapp); configuration->applicationName = STEM_HUMAN_READABLE_TARGET_NAME; configuration->windowTitle = "Renderer"; configuration->displayMode.depthBuffer = true; #elif defined(STEM_PLATFORM_android) void EGLTarget_configure(struct EGLShellConfiguration * configuration) { configuration->displayMode.depthSize = 24; #else void GLUTTarget_configure(int argc, const char ** argv, struct GLUTShellConfiguration * configuration) { configuration->windowTitle = "Renderer"; configuration->displayMode.depthBuffer = true; #endif scaleFactor = Shell_getDisplayScaleFactor(Shell_getDisplayIndexFromWindow()); registerShellCallbacks(); } void Target_init() { uint8_t checkerboardPixels[] = { 0xFF, 0x00, 0x00, 0xFF }; uint8_t texturePixels[] = { 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0xFF }; uint8_t sdfPixels16x16[] = { 0x00, 0x00, 0x0E, 0x20, 0x2B, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x2C, 0x29, 0x27, 0x44, 0x61, 0x74, 0x00, 0x07, 0x23, 0x3B, 0x4A, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x48, 0x36, 0x52, 0x6E, 0x83, 0x0E, 0x23, 0x31, 0x4F, 0x68, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x63, 0x48, 0x61, 0x7C, 0x7C, 0x20, 0x3B, 0x4F, 0x54, 0x74, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x6C, 0x52, 0x6E, 0x86, 0x73, 0x2B, 0x4A, 0x68, 0x74, 0x74, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x8B, 0x6C, 0x61, 0x7C, 0x7C, 0x64, 0x2C, 0x4C, 0x6C, 0x8B, 0x8B, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x6C, 0x63, 0x6E, 0x86, 0x73, 0x56, 0x2C, 0x4C, 0x6C, 0x8B, 0x8B, 0x6C, 0x4C, 0x4C, 0x4C, 0x4C, 0x4C, 0x54, 0x74, 0x7C, 0x64, 0x48, 0x2C, 0x4C, 0x6C, 0x8B, 0x8B, 0x6C, 0x4C, 0x57, 0x64, 0x64, 0x64, 0x64, 0x73, 0x73, 0x56, 0x39, 0x2C, 0x4C, 0x6C, 0x8B, 0x8B, 0x6C, 0x4C, 0x64, 0x83, 0x83, 0x83, 0x83, 0x7C, 0x5C, 0x46, 0x2B, 0x2C, 0x4C, 0x6C, 0x8B, 0x8B, 0x6C, 0x4C, 0x64, 0x83, 0xA3, 0xA3, 0x9B, 0x7C, 0x5C, 0x3C, 0x1C, 0x2C, 0x4C, 0x6C, 0x8B, 0x8B, 0x6C, 0x4C, 0x64, 0x83, 0xA3, 0xBB, 0x9B, 0x7C, 0x5C, 0x3C, 0x1C, 0x2C, 0x4C, 0x6C, 0x8B, 0x8B, 0x6C, 0x4C, 0x64, 0x83, 0xA3, 0xA3, 0x9B, 0x7C, 0x5C, 0x3C, 0x1C, 0x2C, 0x4C, 0x6C, 0x8B, 0x8B, 0x6C, 0x4C, 0x64, 0x83, 0x83, 0x83, 0x83, 0x7C, 0x5C, 0x3C, 0x1C, 0x2B, 0x4A, 0x68, 0x74, 0x74, 0x68, 0x4A, 0x57, 0x64, 0x64, 0x64, 0x64, 0x64, 0x51, 0x36, 0x18, 0x20, 0x3B, 0x4F, 0x54, 0x54, 0x4F, 0x3B, 0x3D, 0x44, 0x44, 0x44, 0x44, 0x44, 0x39, 0x24, 0x0A, 0x0E, 0x23, 0x31, 0x34, 0x34, 0x31, 0x23, 0x1F, 0x24, 0x24, 0x24, 0x24, 0x24, 0x1C, 0x0C, 0x00 }; uint8_t whitePixel[1] = {0xFF}; renderer = Renderer_create(); pipelineConfiguration2D = default2DRenderPipelineConfiguration(RENDER_BLEND_NONE); pipelineConfiguration3D = default3DRenderPipelineConfiguration(RENDER_BLEND_NONE); renderLayer2D = RenderLayer_create(RENDER_LAYER_SORT_NONE, NULL, NULL); renderLayer3D = RenderLayer_create(RENDER_LAYER_SORT_NONE, NULL, NULL); renderTarget = RenderTarget_create(FBO_WIDTH, FBO_HEIGHT, true, true); checkerboardTexture = Texture_createWithTexels2D(checkerboardPixels, 2, 2, 1, TEXEL_COMPONENT_UINT8_NORM, TEXEL_SWIZZLE_R_R | TEXEL_SWIZZLE_G_R | TEXEL_SWIZZLE_B_R | TEXEL_SWIZZLE_A_1, TEXTURE_OPTION_MAGNIFY_NEAREST | TEXTURE_OPTION_REPEAT_X | TEXTURE_OPTION_REPEAT_Y | TEXTURE_OPTION_FILTER_ANISOTROPIC); solidColorTexture = Texture_createWithTexels2D(whitePixel, 1, 1, 1, TEXEL_COMPONENT_UINT8_NORM, TEXEL_SWIZZLE_R_R | TEXEL_SWIZZLE_G_R | TEXEL_SWIZZLE_B_R | TEXEL_SWIZZLE_A_1, 0); texture = Texture_createWithTexels2D(texturePixels, 2, 2, 4, TEXEL_COMPONENT_UINT8_NORM, TEXEL_SWIZZLE_DEFAULT, TEXTURE_OPTION_MAGNIFY_NEAREST); textureSDF = Texture_createWithTexels2D(sdfPixels16x16, 16, 16, 1, TEXEL_COMPONENT_UINT8_NORM, TEXEL_SWIZZLE_R_R | TEXEL_SWIZZLE_G_R | TEXEL_SWIZZLE_B_R | TEXEL_SWIZZLE_A_1, 0); Shader * shader3DStatic = ShaderCollection_get3DLitShader(); Shader * shader3DAnimated = ShaderCollection_get3DLitAnimatedShader(); Shader * shader2DTextured = ShaderCollection_get2DMultitextureShader(); Shader * shader2DSDF = ShaderCollection_get2DSDFMultitextureShader(); perspectiveProjectionUniform = initShaderUniformConfiguration(shader3DStatic, ATOM("projectionTransform")); orthoProjectionUniform = initShaderUniformConfiguration(shader2DTextured, ATOM("projectionTransform")); viewTransformUniform = initShaderUniformConfiguration(shader3DStatic, ATOM("viewTransform")); shaderConfiguration3D = ShaderConfiguration3DLit_create(shader3DStatic); call_virtual(referenceProjectionMatrix, shaderConfiguration3D, &perspectiveProjectionUniform); call_virtual(referenceViewMatrix, shaderConfiguration3D, &viewTransformUniform); call_virtual(setMaterial, shaderConfiguration3D, COLOR4f(1.0f, 1.0f, 1.0f, 1.0f), 0.875f, 32.0f, 0.0f); call_virtual(setTexture, shaderConfiguration3D, 0, checkerboardTexture, false); shaderConfiguration3DAnimated = ShaderConfiguration3DLitAnimated_create(shader3DAnimated, NULL); call_virtual(referenceProjectionMatrix, shaderConfiguration3DAnimated, &perspectiveProjectionUniform); call_virtual(referenceViewMatrix, shaderConfiguration3DAnimated, &viewTransformUniform); call_virtual(setMaterial, shaderConfiguration3DAnimated, COLOR4f(1.0f, 1.0f, 1.0f, 1.0f), 0.875f, 32.0f, 0.0f); call_virtual(setTexture, shaderConfiguration3DAnimated, 0, checkerboardTexture, false); shaderConfiguration3DAnimatedArmature = ShaderConfiguration3DLitAnimated_create(shader3DAnimated, NULL); call_virtual(referenceProjectionMatrix, shaderConfiguration3DAnimatedArmature, &perspectiveProjectionUniform); call_virtual(referenceViewMatrix, shaderConfiguration3DAnimatedArmature, &viewTransformUniform); call_virtual(setMaterial, shaderConfiguration3DAnimatedArmature, COLOR4f(1.0f, 1.0f, 0.9375f, 1.0f), 0.875f, 32.0f, 0.0f); call_virtual(setTexture, shaderConfiguration3DAnimatedArmature, 0, solidColorTexture, false); shaderConfiguration2D = ShaderConfiguration2DTexture_create(shader2DTextured); call_virtual(setTexture, shaderConfiguration2D, 0, texture, false); call_virtual(referenceProjectionMatrix, shaderConfiguration2D, &orthoProjectionUniform); shaderConfiguration2DSDF = ShaderConfiguration2DSDF_create(shader2DSDF); call_virtual(setTexture, shaderConfiguration2DSDF, 0, textureSDF, false); call_virtual(referenceProjectionMatrix, shaderConfiguration2DSDF, &orthoProjectionUniform); ShaderConfiguration * fboShaderConfiguration = ShaderCollection_getRenderTargetShaderConfiguration(); call_virtual(setTexture, fboShaderConfiguration, 0, renderTarget->colorTexture, false); ShaderConfiguration * fboAreaShaderConfiguration = ShaderCollection_getRenderTargetAreaFilterShaderConfiguration(); call_virtual(setTexture, fboAreaShaderConfiguration, 0, renderTarget->colorTexture, false); updateProjection(); initScene1(); Shell_mainLoop(); }