examples/code/cache/cache.cpp

examples/code/cache/cache.cpp
/*
Copyright 2014 Autodesk, Inc. All rights reserved.
Use of this software is subject to the terms of the Autodesk license agreement
provided at the time of installation or download, or which otherwise
accompanies this software in either electronic or hard copy form.
*/
/*
Beast API Sample: Cache
The purpose of this sample is to demonstrate how to use the API to:
1. Create a global cache
2. Create a resource in the cache
3. Reuse the resource in subsequent renderings.
*/
#define _USE_MATH_DEFINES // for M_PI
#include <cmath>
#include <iostream>
#include <sstream>
#include "vecmath.h"
#include "utils.h"
#include "primitives.h"
#include "textures.h"
// Make sure we have a unicode safe cout define
#ifdef UNICODE
#define tcout std::wcout
#else
#define tcout std::cout
#endif
enum RunMode {
RM_CLEAR,
RM_GLOBAL,
RM_LOCAL,
};
RunMode getRunMode(const std::basic_string<TCHAR>& rm) {
if(rm == _T("clear")) {
return RM_CLEAR;
}
if(rm == _T("global")) {
return RM_GLOBAL;
}
if(rm == _T("local")) {
return RM_LOCAL;
}
throw std::runtime_error("Invalid runmode");
}
int _tmain(int argc, _TCHAR* argv[])
{
try {
std::vector<std::basic_string<TCHAR> > arguments(argv, argv + argc);
if(arguments.size() > 2) {
tcout << _T("Error, at most one argument") << std::endl;
tcout << _T("Supported arguments:") << std::endl;
tcout << _T(" clear : Clears the cache") << std::endl;
tcout << _T(" global : Does a rendering using a global cache, reusing assets if possible (default)") << std::endl;
tcout << _T(" local : Does a rendering using a local cache, won't reuse assets") << std::endl;
}
// Default to RM_GLOBAL
RunMode runmode = (arguments.size() == 1 ? RM_GLOBAL : getRunMode(arguments[1]));
// Route errors to stderr
#if defined(WIN32)
// Route general info to debug output (i.e output window in
// visual studio)
#else
// Route general info to std output
#endif
std::basic_string<TCHAR> dir(_T("../../../temp/cacheTest"));
switch(runmode) {
case RM_CLEAR:
tcout << "Clearing cache...";
bex::apiCall(ILBCreateManager(dir.c_str(), ILB_CS_GLOBAL, bex::getLicenseKey().c_str(), &bmh));
bex::apiCall(ILBClearCache(bmh));
tcout << " Done!" << std::endl;
return 0;
case RM_GLOBAL:
tcout << "Creating a global cache!" << std::endl;
bex::apiCall(ILBCreateManager(dir.c_str(), ILB_CS_GLOBAL, bex::getLicenseKey().c_str(), &bmh));
break;
case RM_LOCAL:
tcout << "Creating a local cache!" << std::endl;
bex::apiCall(ILBCreateManager(dir.c_str(), ILB_CS_LOCAL, bex::getLicenseKey().c_str(), &bmh));
break;
default:
throw std::runtime_error("Invalid runmode");
}
// Set the path to the Beast binaries
bex::apiCall(ILBSetBeastPath(bmh, _T("../../../bin")));
// Create ball and a plane meshes
std::basic_string<TCHAR> sphereName(_T("Sphere"));
std::basic_string<TCHAR> floorName(_T("Floor"));
std::basic_string<TCHAR> sphereMatName(_T("SphereMaterial"));
std::basic_string<TCHAR> floorMatName(_T("FloorMaterial"));
ILBMeshHandle sphereMesh;
if(!bex::findCachedMesh(bmh, sphereName, sphereMesh, tcout)){
// Create a monster sphere to make sure it's painful not
// to use the cache
sphereMesh = bex::createSphere(bmh, sphereName, sphereMatName, 600, 400);
}
ILBMeshHandle floorMesh;
if(!bex::findCachedMesh(bmh, floorName, floorMesh, tcout)) {
floorMesh = bex::createPlane(bmh, floorName, floorMatName);
}
std::basic_string<TCHAR> texName(_T("Mandelbrot"));
if(!bex::findCachedTexture(bmh, texName, texture, tcout)) {
// Make sure it's painful to get a cache miss!
texture = bex::createMandelbrotTexture(bmh, texName, bex::ColorRGB(1.0f, .7f, .7f), 1000, 1000);
}
// Create a scene
bex::apiCall(ILBBeginScene(bmh, _T("SimpleScene"), &scene));
// Create an instance of the plane that will be a floor
ILBInstanceHandle floorInstance;
bex::Matrix4x4 floorTrans = bex::scaleTranslation(bex::Vec3(10.0f, 1.0f, 10.0f),
bex::Vec3(0.0f, -5.0f, 0.0f));
bex::apiCall(ILBCreateInstance(scene, floorMesh, _T("FloorInstance"), &floorTrans, &floorInstance));
// Create 5 instances of the sphere on the plane
const int spheres = 5;
const float sphereRad = 2.0f;
const float spherePosRadius = 5.0f;
for(int i = 0; i < spheres; ++i) {
float angle = static_cast<float>(M_PI) * 2.0f * static_cast<float>(i) / static_cast<float>(spheres);
float x = cosf(angle) * spherePosRadius;
float z = sinf(angle) * spherePosRadius;
bex::Matrix4x4 trans = bex::scaleTranslation(bex::Vec3(sphereRad, sphereRad, sphereRad),
bex::Vec3(x, -3.0f, z));
ILBInstanceHandle tempInstance;
std::basic_stringstream<TCHAR> sphereName;
sphereName << _T("SphereInstance_") << i;
bex::apiCall(ILBCreateInstance(scene, sphereMesh, sphereName.str().c_str(), &trans, &tempInstance));
}
// Create the floor material
bex::apiCall(ILBCreateMaterial(scene, floorMatName.c_str(), &floorMat));
bex::apiCall(ILBSetMaterialTexture(floorMat, ILB_CC_DIFFUSE, texture));
// Create the sphere material
ILBMaterialHandle sphereMat;
bex::apiCall(ILBCreateMaterial(scene, sphereMatName.c_str(), &sphereMat));
bex::apiCall(ILBSetMaterialColor(sphereMat, ILB_CC_DIFFUSE, &bex::ColorRGBA(.3f, .3f, .3f, 1.0f)));
bex::apiCall(ILBSetMaterialColor(sphereMat, ILB_CC_SPECULAR, &bex::ColorRGBA(1.0f, 1.0f, 1.0f, 1.0f)));
bex::apiCall(ILBSetMaterialScale(sphereMat, ILB_CC_REFLECTION, .1f));
bex::apiCall(ILBSetMaterialScale(sphereMat, ILB_CC_SHININESS, 15.0f));
// Create a directional light that casts soft shadows
bex::apiCall(ILBCreateDirectionalLight(scene,
_T("Sun"),
&bex::directionalLightOrientation(bex::Vec3(1.0, -1.0f, -1.0f)),
&bex::ColorRGB(1.0f, 1.0f, .8f),
&light));
bex::apiCall(ILBSetCastShadows(light, true));
bex::apiCall(ILBSetShadowSamples(light, 32));
bex::apiCall(ILBSetShadowAngle(light, .1f));
ILBLightHandle skyLight;
bex::apiCall(ILBCreateSkyLight(scene,
_T("SkyLight"),
&bex::identity(),
&bex::ColorRGB(0.21f, 0.21f, 0.3f),
&skyLight));
// Setup a camera to render from
bex::apiCall(ILBCreatePerspectiveCamera(scene,
_T("Camera"),
&bex::setCameraMatrix(bex::Vec3(.3f, .5f, 15.0f),
bex::Vec3(.1f, -0.3f, -1.0f),
bex::Vec3(0.0f, 1.0f, 0.0f)),
&camera));
// Finalize the scene
bex::apiCall(ILBEndScene(scene));
bex::apiCall(ILBCreateJob(bmh, _T("TestJob"), scene, _T("../../data/simpleFG.xml"), &job));
// Create pass
ILBRenderPassHandle fullShadingPass;
bex::apiCall(ILBCreateFullShadingPass(job, _T("fullShading"), &fullShadingPass));
// Create Target
ILBTargetHandle cameraTarget;
bex::apiCall(ILBCreateCameraTarget(job, _T("cameraTarget"), camera, 640, 480, &cameraTarget));
// Add pass to targets
bex::apiCall(ILBAddPassToTarget(cameraTarget, fullShadingPass));
// Finally render the scene
if(!bex::renderJob(job, tcout)) {
return 1;
}
return 0;
} catch(bex::Exception& ex) {
ILBStringHandle errorString;
ILBStringHandle extendedError;
ILBErrorToString(ex.status, &errorString);
tcout << "Beast API error" << std::endl;
tcout << "Error: " << bex::convertStringHandle(errorString) << std::endl;
tcout << "Info: " << bex::convertStringHandle(extendedError) << std::endl;
return 1;
} catch(std::exception& ex) {
tcout << "Standard exception" << std::endl;
tcout << "Error: " << ex.what() << std::endl;;
return 1;
}
}