#include "3dmodelio/ArmatureAnimationIO.h" #include "3dmodelio/ArmatureIO.h" #include "3dmodelio/MeshConfigurationRegistry.h" #include "3dmodelio/MeshData.h" #include "3dmodelio/Obj3DModelIO.h" #include "3dmodelio/TextureAtlasData.h" #include "binaryserialization/BinarySerializationShared.h" #include "gamemath/ArmatureAnimation.h" #include "gamemath/Matrix4x4f.h" #include "gamemath/OrbitCamera.h" #include "gamemath/TextureAtlas.h" #include "jsonserialization/JSONSerializationShared.h" #include "pngimageio/PNGImageIO.h" //#include "renderer/MeshRenderable.h" #include "renderer/Renderer.h" //#include "renderer/SpriteRenderable.h" #include "resourcemanager/ResourceManager.h" #include "serialization/DeserializationTypeDetector.h" #include "shell/Shell.h" #include "shell/ShellCallbacks.h" #include "shell/ShellKeyCodes.h" #include "utilities/AutoFreePool.h" #include "utilities/IOUtilities.h" #include "utilities/Ranrot.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 #include "glutshell/GLUTTarget.h" #endif #include #include #include #include #include #include #include #ifdef STEM_PLATFORM_android #include #define printf(format, ...) __android_log_print(ANDROID_LOG_INFO, "3DModelIO", format, ##__VA_ARGS__); #define fprintf(stderr, format, ...) __android_log_print(ANDROID_LOG_INFO, "3DModelIO", format, ##__VA_ARGS__); #endif #define PROJECTION_FOV 60.0f static ResourceManager * resourceManager; static DeserializationTypeDetector * typeDetector; static ShaderRegistry * shaderRegistry; static MeshConfigurationRegistry * meshConfigurationRegistry; static Renderable * renderable; static Renderable * armatureRenderable; static Texture * blankTexture; static Box6f renderableBounds; static Armature * armature; static ArmatureAnimation * animation; static AnimationState * animationState; static Renderer * renderer; static RenderLayer * renderLayer2D; static RenderLayer * renderLayer3D; static OrbitCamera * camera; static ShaderUniformConfiguration perspectiveProjectionUniform; static ShaderUniformConfiguration orthoProjectionUniform; static ShaderUniformConfiguration viewTransformUniform; static ShaderConfiguration3DAnimated * shaderConfiguration3DAnimatedArmature; static ShaderConfiguration2DTextured * shaderConfiguration2D; 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 textureAtlasMode; static TextureAtlas * textureAtlas; static unsigned int spriteCount; static ShaderConfiguration2DTextured * shaderConfiguration2D; static SpriteRenderable ** spriteRenderables; static Color4f clearColor; static bool Target_draw(double referenceTime, double activeDrawDelta) { if (animating && animationState != NULL && animation != NULL) { AnimationState_resetAllBones(animationState); Animation_poseAnimationStateAtTime(animation, animationState, referenceTime - animationStartTime, 1.0f); AnimationState_computeBoneTransforms(animationState); Shell_redisplay(); } Renderer_clear(renderer, clearColor); if (textureAtlasMode) { Renderer_drawLayer(renderer, renderLayer2D, referenceTime, activeDrawDelta); } else { ShaderUniformConfiguration_setMat4_Matrix4x4f(&viewTransformUniform, call_virtual(getTransform, camera)); Renderer_drawLayer(renderer, renderLayer3D, referenceTime, activeDrawDelta); } AutoFreePool_empty(); return true; } static void updateProjection() { Matrix4x4f perspectiveMatrix = Matrix4x4f_perspective(MATRIX4x4f_IDENTITY, PROJECTION_FOV, viewRatio, 0.02f, 40.0f); ShaderUniformConfiguration_setMat4_Matrix4x4f(&perspectiveProjectionUniform, perspectiveMatrix); Matrix4x4f orthoMatrix = Matrix4x4f_ortho(MATRIX4x4f_IDENTITY, -viewRatio, viewRatio, -1.0f, 1.0f, -1.0f, 1.0f); ShaderUniformConfiguration_setMat4_Matrix4x4f(&orthoProjectionUniform, orthoMatrix); } static void purgeAllRenderables() { RenderLayer_removeAllRenderables(renderLayer2D); RenderLayer_removeAllRenderables(renderLayer3D); if (textureAtlas != NULL) { TextureAtlas_dispose(textureAtlas); textureAtlas = NULL; } if (spriteRenderables != NULL) { unsigned int spriteIndex; for (spriteIndex = 0; spriteIndex < spriteCount; spriteIndex++) { SpriteRenderable_dispose(spriteRenderables[spriteIndex]); } free(spriteRenderables); spriteRenderables = NULL; spriteCount = 0; } if (armature != NULL) { ResourceManager_releaseResource(resourceManager, armature); armature = NULL; } if (animation != NULL) { Animation_dispose(animation); animation = NULL; } if (animationState != NULL) { AnimationState_dispose(animationState); animationState = NULL; } if (renderable != NULL) { MeshRenderable_dispose(renderable); renderable = NULL; } if (armatureRenderable != NULL) { MeshRenderable_dispose(armatureRenderable); armatureRenderable = NULL; } ResourceManager_purgeAll(resourceManager); } 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.left) { bounds.left = position.x; } if (position.x > bounds.right) { bounds.right = position.x; } if (position.y < bounds.bottom) { bounds.bottom = position.y; } if (position.y > bounds.top) { bounds.top = position.y; } if (position.z < bounds.back) { bounds.back = position.z; } if (position.z > bounds.front) { bounds.front = position.z; } } return bounds; } static void useMesh(MeshData * meshData) { struct ShaderRegistry_entry * shaderEntry = ShaderRegistry_lookup(shaderRegistry, Atom_getExisting(meshData->shaderName)); if (shaderEntry == NULL) { fprintf(stderr, "Error: Mesh specifies shader \"%s\", which is not registered; cannot display\n", meshData->shaderName); return; } if (meshData->vertexFormat != shaderEntry->shader->vertexFormat && VertexFormat_compare(meshData->vertexFormat, shaderEntry->shader->vertexFormat)) { fprintf(stderr, "Error: Mesh specifies a vertex format incompatible with the one its shader uses; cannot display\n"); return; } purgeAllRenderables(); textureAtlasMode = false; animating = false; clearColor = COLOR4f(0.0f, 0.125f, 0.25f, 0.0f); if (StemObject_isClassOrSubclass(meshData->configurationData, &MeshConfigurationDataSurfaceMaterialArmature_class)) { armature = ResourceManager_referenceResource(resourceManager, ATOM("armature"), ((MeshConfigurationDataSurfaceMaterialArmature *) meshData->configurationData)->armatureName); if (armature != NULL) { animationState = AnimationState_create(armature); shaderConfiguration3DAnimatedArmature->animationState = animationState; VertexBuffer * armatureVertexBuffer = Armature_createDebugVertexBuffer(armature, renderer); armatureRenderable = MeshRenderable_create(PRIMITIVE_TRIANGLES, shaderConfiguration3DAnimatedArmature, armatureVertexBuffer, true); armatureRenderable->visible = false; RenderLayer_addRenderable(renderLayer3D, armatureRenderable, 0); } else { fprintf(stderr, "Couldn't load armature \"%s\" for mesh \"%s\"\n", ((MeshConfigurationDataSurfaceMaterialArmature *) meshData->configurationData)->armatureName, meshData->name); } } ShaderConfiguration * shaderConfiguration = shaderEntry->createShaderConfiguration(shaderEntry->shader, meshData->configurationData); if (StemObject_isClassOrSubclass(shaderConfiguration, &ShaderConfiguration3DStatic_class)) { call_virtual(setLights, (ShaderConfiguration3DStatic *) shaderConfiguration, 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), COLOR3f(0.1f, 0.1f, 0.105f)); if (meshData->textureCount == 0) { call_virtual(setTexture, shaderConfiguration, 0, blankTexture, false); } if (animationState != NULL && StemObject_isClassOrSubclass(shaderConfiguration, &ShaderConfiguration3DAnimated_class)) { ((ShaderConfiguration3DAnimated *) shaderConfiguration)->animationState = animationState; } } call_virtual(referenceProjectionMatrix, shaderConfiguration, &perspectiveProjectionUniform); call_virtual(referenceViewMatrix, shaderConfiguration, &viewTransformUniform); for (unsigned int textureIndex = 0; textureIndex < meshData->textureCount; textureIndex++) { BitmapImage * image = ResourceManager_referenceResource(resourceManager, ATOM("png"), meshData->textures[textureIndex].name); if (image != NULL) { Texture * texture = Texture_createWithTexels2D(image->width, image->height, BitmapImage_pixelFormatBytes(image->pixelFormat), image->pixels, meshData->textures[textureIndex].options); call_virtual(setTexture, shaderConfiguration, meshData->textures[textureIndex].index, texture, true); ResourceManager_releaseResource(resourceManager, image); } else { fprintf(stderr, "Couldn't load texture image \"%s\"\n", meshData->textures[textureIndex].name); } } VertexBuffer * vertexBuffer = VertexBuffer_create(shaderConfiguration->shader->vertexFormat, meshData->vertices, meshData->vertexCount, meshData->indexes, meshData->indexCount, VERTEX_BUFFER_USAGE_STATIC); renderable = MeshRenderable_create(meshData->primitiveType, shaderConfiguration, vertexBuffer, true); renderableBounds = getVertexDataBounds(meshData->vertices, meshData->vertexCount, shaderConfiguration->shader->vertexFormat); RenderLayer_addRenderable(renderLayer3D, renderable, 0); Shell_redisplay(); } static void useAnimation(Animation * animationToUse) { if (animation != NULL) { Animation_dispose(animation); } animation = animationToUse; animationStartTime = Shell_getCurrentTime(); animating = true; Shell_redisplay(); } static void updateSpriteLayout() { unsigned int spriteIndex; unsigned int columnCount; float scale; unsigned int maxDimension = 1; Vector2f pixelSize; columnCount = ceil(sqrt(spriteCount)); // TODO: Make rectangular; how? for (spriteIndex = 0; spriteIndex < spriteCount; spriteIndex++) { pixelSize = TextureAtlas_lookupEntryDimensions(spriteRenderables[spriteIndex]->atlas, spriteRenderables[spriteIndex]->atlasKey, TEXTUREATLAS_SIZE_AUTO, TEXTUREATLAS_SIZE_AUTO); if (pixelSize.x > maxDimension) { maxDimension = pixelSize.x; } if (pixelSize.y > maxDimension) { maxDimension = pixelSize.y; } } scale = 2.0f / maxDimension / columnCount; // TODO: Add some borders? for (spriteIndex = 0; spriteIndex < spriteCount; spriteIndex++) { pixelSize = TextureAtlas_lookupEntryDimensions(spriteRenderables[spriteIndex]->atlas, spriteRenderables[spriteIndex]->atlasKey, TEXTUREATLAS_SIZE_AUTO, TEXTUREATLAS_SIZE_AUTO); spriteRenderables[spriteIndex]->offset = VECTOR2f(-1.0f + (spriteIndex % columnCount + 1) * 2.0f / columnCount, -1.0f + (spriteIndex / columnCount + 1) * 2.0f / columnCount); spriteRenderables[spriteIndex]->size = VECTOR2f(pixelSize.x * scale, pixelSize.y * scale); } } static void useTextureAtlas(TextureAtlasData * atlasData) { BitmapImage * image; purgeAllRenderables(); textureAtlasMode = true; animating = false; clearColor = COLOR4f(0.0f, 0.0625f, 0.0f, 0.0f); image = ResourceManager_referenceResource(resourceManager, ATOM("png"), atlasData->textureMapName); if (image != NULL) { unsigned int spriteIndex; textureAtlas = TextureAtlasData_createTextureAtlas(atlasData, image); ResourceManager_releaseResource(resourceManager, image); call_virtual(setTexture, shaderConfiguration2D, 0, textureAtlas->texture, false); spriteCount = atlasData->entryCount; spriteRenderables = malloc(sizeof(SpriteRenderable *) * spriteCount); for (spriteIndex = 0; spriteIndex < spriteCount; spriteIndex++) { spriteRenderables[spriteIndex] = SpriteRenderable_create(textureAtlas, atlasData->entries[spriteIndex].name, shaderConfiguration2D, VECTOR2f(0.5f, 0.5f), VECTOR2f_ZERO, VECTOR2f_ZERO, false, TextureAtlas_normal, COLOR4f(1.0f, 1.0f, 1.0f, 1.0f)); RenderLayer_addRenderable(renderLayer2D, spriteRenderables[spriteIndex], 0); } updateSpriteLayout(); } else { fprintf(stderr, "Couldn't load texture image \"%s\"\n", atlasData->textureMapName); } Shell_redisplay(); } static const char * filePathForResource(Atom resourceName) { const char * filePath = NULL; filePath = ResourceManager_resolveFilePath(resourceManager, resourceName); if (filePath == NULL) { filePath = resourceName; } return filePath; } static void * loadMeshResource(Atom resourceName, void * context) { DeserializationContext * deserializationContext = DeserializationTypeDetector_createDeserializationContextWithFile(typeDetector, filePathForResource(resourceName)); if (deserializationContext == NULL) { fprintf(stderr, "Couldn't open or determine type of \"%s\" (errno = %d)\n", resourceName, errno); return NULL; } MeshData * meshData = MeshData_deserialize(deserializationContext, shaderRegistry, meshConfigurationRegistry); call_virtual(dispose, deserializationContext); return meshData; } static void unloadMeshResource(void * resource, void * context) { MeshData_dispose(resource); } void * loadPNGResource(const char * resourceName, void * context) { return PNGImageIO_loadPNGFile(filePathForResource(resourceName), BITMAP_PIXEL_FORMAT_RGBA_8888, true); } void unloadPNGResource(void * resource, void * context) { BitmapImage_dispose(resource); } static void * loadArmatureResource(Atom resourceName, void * context) { DeserializationContext * deserializationContext = DeserializationTypeDetector_createDeserializationContextWithFile(typeDetector, filePathForResource(resourceName)); if (deserializationContext == NULL) { fprintf(stderr, "Couldn't open or determine type of \"%s\" (errno = %d)\n", resourceName, errno); return NULL; } Armature * armature = Armature_deserialize(deserializationContext); call_virtual(dispose, deserializationContext); return armature; } static void unloadArmatureResource(void * resource, void * context) { Armature_dispose(resource); } static void loadObjFile(const char * filePath) { MeshData * meshData = Obj3DModelIO_loadFile(filePath); useMesh(meshData); call_virtual(setMaterial, (ShaderConfiguration3DStatic *) renderable->shaderConfiguration, COLOR4f(1.0f, 1.0f, 0.9375f, 1.0f), 0.875f, 32.0f, 0.0f); MeshData_dispose(meshData); } static void loadObjResource(const char * fileName) { const char * resourcePath = Shell_getResourcePath(); char path[PATH_MAX]; snprintf_safe(path, sizeof(path), "%s/%s", resourcePath, fileName); MeshData * meshData = Obj3DModelIO_loadResourceFile(path); useMesh(meshData); call_virtual(setMaterial, (ShaderConfiguration3DStatic *) renderable->shaderConfiguration, COLOR4f(1.0f, 1.0f, 0.9375f, 1.0f), 0.875f, 32.0f, 0.0f); MeshData_dispose(meshData); } static void loadStem3DMesh(const char * filePath) { DeserializationContext * context = DeserializationTypeDetector_createDeserializationContextWithFile(typeDetector, filePath); if (context == NULL) { fprintf(stderr, "Couldn't open or determine type of \"%s\" (errno = %d)\n", filePath, errno); return; } MeshData * meshData = MeshData_deserialize(context, shaderRegistry, meshConfigurationRegistry); if (meshData == NULL) { fprintf(stderr, "Couldn't load \"%s\" as mesh data (serialization status %d)\n", filePath, context->status); } else { ResourceManager_addSearchPath(resourceManager, getDirectory(filePath)); useMesh(meshData); MeshData_dispose(meshData); } call_virtual(dispose, context); } static void loadAnimation(const char * filePath) { DeserializationContext * context = DeserializationTypeDetector_createDeserializationContextWithFile(typeDetector, filePath); if (context == NULL) { fprintf(stderr, "Couldn't open or determine type of \"%s\" (errno = %d)\n", filePath, errno); return; } Animation * loadedAnimation = Animation_deserialize(context); if (loadedAnimation == NULL) { fprintf(stderr, "Couldn't load \"%s\" as animation data (serialization status %d)\n", filePath, context->status); } else { useAnimation(loadedAnimation); } call_virtual(dispose, context); } static void loadTextureAtlas(const char * filePath) { DeserializationContext * context = DeserializationTypeDetector_createDeserializationContextWithFile(typeDetector, filePath); if (context == NULL) { fprintf(stderr, "Couldn't open or determine type of \"%s\" (errno = %d)\n", filePath, errno); return; } TextureAtlasData * atlasData = TextureAtlasData_deserialize(context); if (atlasData == NULL) { fprintf(stderr, "Couldn't load \"%s\" as texture atlas data (serialization status %d)\n", filePath, context->status); } else { ResourceManager_addSearchPath(resourceManager, getDirectory(filePath)); useTextureAtlas(atlasData); TextureAtlasData_dispose(atlasData); } call_virtual(dispose, context); } static void Target_keyDown(unsigned int charCode, unsigned int keyCode, unsigned int modifiers, bool isRepeat, double referenceTime) { switch (keyCode) { case KEY_CODE_O: { const char * filePath; if (Shell_openFileDialog(NULL, &filePath, 0, NULL)) { const char * fileExtension = getFileExtension(filePath); if (!strcmp(fileExtension, "obj")) { loadObjFile(filePath); } else if (!strcmp(fileExtension, "mesh")) { loadStem3DMesh(filePath); } else if (!strcmp(fileExtension, "animation")) { loadAnimation(filePath); } else if (!strcmp(fileExtension, "atlas")) { loadTextureAtlas(filePath); } else { DeserializationContext * context = DeserializationTypeDetector_createDeserializationContextWithFile(typeDetector, filePath); if (context == NULL) { fprintf(stderr, "Couldn't open or determine type of \"%s\" (errno = %d)\n", filePath, errno); break; } call_virtual(beginStructure, context, NULL); const char * type = call_virtual(readString, context, "format_type"); if (type != NULL) { if (!strcmp(type, MESHDATA_FORMAT_TYPE)) { loadStem3DMesh(filePath); } else if (!strcmp(type, ANIMATION_FORMAT_TYPE)) { loadAnimation(filePath); } else if (!strcmp(type, TEXTUREATLASDATA_FORMAT_TYPE)) { loadTextureAtlas(filePath); } else { fprintf(stderr, "File \"%s\" is of format_type \"%s\", which this test harness doesn't know how to load\n", filePath, type); } } else { fprintf(stderr, "Couldn't determine type of file \"%s\"; unable to load\n", filePath); } call_virtual(dispose, context); } } 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 = referenceTime; } else { animating = true; animationStartTime += referenceTime - lastAnimationTime; Shell_redisplay(); } break; case KEY_CODE_F: if (!textureAtlasMode) { OrbitCamera_frameBoundingBox(camera, renderableBounds, PROJECTION_FOV, viewRatio); Shell_redisplay(); } break; case KEY_CODE_P: { if (animationState == NULL) { break; } if (modifiers & MODIFIER_SHIFT_BIT) { AnimationState_resetAllBones(animationState); } else { unsigned int boneIndex; float angle; Vector3f axis; for (boneIndex = 0; boneIndex < armature->boneCount; boneIndex++) { axis.x = frand(1.0f); axis.y = frand(1.0f); axis.z = frand(1.0f); angle = frand(0.05f); Vector3f_normalize(&axis); Quaternionf_rotate(&animationState->boneStates[boneIndex].rotation, axis, angle); } } AnimationState_computeBoneTransforms(animationState); Shell_redisplay(); break; } case KEY_CODE_SPACE: animationStartTime = referenceTime; Shell_redisplay(); break; } } static void Target_keyUp(unsigned int keyCode, unsigned int modifiers, double referenceTime) { } static void Target_keyModifiersChanged(unsigned int modifiers, double referenceTime) { } static void Target_mouseDown(unsigned int buttonNumber, float x, float y, unsigned int modifierFlags, double referenceTime) { Shell_setMouseDeltaMode(true); } static void Target_mouseUp(unsigned int buttonNumber, 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) { } 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 (textureAtlasMode) { // ? } 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_scrollWheel(float x, float y, int deltaX, int deltaY, unsigned int modifierFlags, double referenceTime) { } static void Target_resized(unsigned int newWidth, unsigned int newHeight, double referenceTime) { viewWidth = newWidth; viewHeight = newHeight; viewRatio = (float) newWidth / newHeight; scaleFactor = Shell_getDisplayScaleFactor(Shell_getDisplayIndexFromWindow()); if (renderer != NULL) { Renderer_setViewport(renderer, 0, 0, viewWidth, viewHeight); //if (textureAtlasMode) { //updateSpriteLayout(); //} 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_scrollWheelFunc(Target_scrollWheel); 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 = "3DModelIO"; configuration->windowWidth = viewWidth; configuration->windowHeight = viewHeight; 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; #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 = "3DModelIO"; configuration->windowWidth = viewWidth; configuration->windowHeight = viewHeight; configuration->useGLCoreProfile = true; configuration->displayMode.depthBuffer = true; #elif defined(STEM_PLATFORM_linux) void GLXTarget_configure(int argc, const char ** argv, struct GLXShellConfiguration * configuration) { configuration->windowTitle = "3DModelIO"; configuration->displayMode.depthBuffer = true; #elif defined(STEM_PLATFORM_android) void EGLTarget_configure(struct EGLShellConfiguration * configuration) { readResourceFile = EGLShell_readResourceFile; configuration->displayMode.depthSize = 24; #else void GLUTTarget_configure(int argc, const char ** argv, struct GLUTShellConfiguration * configuration) { configuration->windowTitle = "3DModelIO"; configuration->displayMode.depthBuffer = true; #endif scaleFactor = Shell_getDisplayScaleFactor(Shell_getDisplayIndexFromWindow()); registerShellCallbacks(); } void Target_init() { sdrand(time(NULL)); stirrand(50); renderer = Renderer_create(); renderLayer2D = RenderLayer_create(RENDERER_2D_OPAQUE, RENDER_LAYER_SORT_TYPE_ONLY, NULL, NULL); renderLayer3D = RenderLayer_create(RENDERER_3D_OPAQUE, RENDER_LAYER_SORT_TYPE_ONLY, NULL, NULL); clearColor = COLOR4f(0.0f, 0.125f, 0.25f, 0.0f); Shader * shader3DStatic = Renderer_getBuiltInShader(renderer, RENDERER_BUILT_IN_SHADER_3D_STATIC); Shader * shader3DAnimated = Renderer_getBuiltInShader(renderer, RENDERER_BUILT_IN_SHADER_3D_ANIMATED); Shader * shader2DTextured = Renderer_getBuiltInShader(renderer, RENDERER_BUILT_IN_SHADER_2D_TEXTURED); perspectiveProjectionUniform = initShaderUniformConfiguration(shader3DStatic, SHADER_3D_STATIC_UNIFORM_ATOM_projectionTransform); orthoProjectionUniform = initShaderUniformConfiguration(shader2DTextured, SHADER_2D_TEXTURED_UNIFORM_ATOM_projectionTransform); viewTransformUniform = initShaderUniformConfiguration(shader3DStatic, SHADER_3D_STATIC_UNIFORM_ATOM_viewTransform); shaderConfiguration3DAnimatedArmature = ShaderConfiguration3DAnimated_create(shader3DAnimated, NULL); call_virtual(setLights, shaderConfiguration3DAnimatedArmature, 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), COLOR3f(0.1f, 0.1f, 0.105f)); call_virtual(setMaterial, shaderConfiguration3DAnimatedArmature, COLOR4f(1.0f, 1.0f, 0.9375f, 1.0f), 0.875f, 32.0f, 0.0f); call_virtual(referenceProjectionMatrix, shaderConfiguration3DAnimatedArmature, &perspectiveProjectionUniform); call_virtual(referenceViewMatrix, shaderConfiguration3DAnimatedArmature, &viewTransformUniform); uint8_t whitePixel = 0xFF; blankTexture = Texture_createWithTexels2D(1, 1, TEXEL_DATA_GRAY, &whitePixel, 0); call_virtual(setTexture, shaderConfiguration3DAnimatedArmature, 0, blankTexture, false); shaderConfiguration2D = ShaderConfiguration2DTextured_create(shader2DTextured); call_virtual(referenceProjectionMatrix, shaderConfiguration2D, &orthoProjectionUniform); updateProjection(); resourceManager = ResourceManager_create(Shell_getCurrentTime); ResourceManager_addTypeHandler(resourceManager, ATOM("mesh"), loadMeshResource, unloadMeshResource, PURGE_DEFERRED, NULL); ResourceManager_addTypeHandler(resourceManager, ATOM("png"), loadPNGResource, unloadPNGResource, PURGE_DEFERRED, NULL); ResourceManager_addTypeHandler(resourceManager, ATOM("armature"), loadArmatureResource, unloadArmatureResource, PURGE_DEFERRED, NULL); typeDetector = DeserializationTypeDetector_create(); DeserializationTypeDetector_registerDetectionCallback(typeDetector, JSONSerialization_typeDetector); DeserializationTypeDetector_registerDetectionCallback(typeDetector, BinarySerialization_typeDetector); meshConfigurationRegistry = MeshConfigurationRegistry_create(); MeshConfigurationRegistry_registerBuiltInConfigurations(meshConfigurationRegistry); shaderRegistry = ShaderRegistry_create(); ShaderRegistry_registerBuiltInShaders(shaderRegistry, renderer); loadObjResource("suzanne.obj"); camera = OrbitCamera_create(); Shell_mainLoop(); }