This comprehensive code sample includes the essential scanning and processing steps to produce a complete 3D model.The code initializes the scanner and captures a series of frames, registers and processes, then combines them into a single 3D mesh. Functions in the artec::sdk::algorithms namespace handle the processing. Using this sample you can store models, both textured and untextured as well as raw frames into OBJ file. The final step is to display a model in a 3D viewer by calling meshContainer
directly.
#include <iomanip>
#include <iostream>
#include "ScenePresenter.h"
namespace asdk {
};
using asdk::TRef;
const int NumberOfFramesToCapture = 100;
#define ENABLE_TEXTURE_MAPPING
#define OUTPUT_DIR L"scans"
#define SDK_STRINGIFY(x) #x
#define SDK_STRING(x) SDK_STRINGIFY(x)
#define SAFE_SDK_CALL(x) \
{ \
asdk::ErrorCode ec = (x); \
if ( ec != asdk::ErrorCode_OK ) \
{ \
reportError( ec, __FILE__ " [ line " SDK_STRING(__LINE__) " ]"); \
return ec; \
} \
}
{
const wchar_t* msg = L"No error";
switch( ec ){
msg = L"Not enough storage is available to process the operation";
break;
msg = L"Provided argument is invalid";
break;
msg = L"Requested operation is invalid";
break;
msg = L"Data format is unsupported or invalid";
break;
msg = L"Requested scanner is not connected";
break;
msg = L"Requested scanner is not licensed";
break;
msg = L"Requested scanner is already used by someone else";
break;
msg = L"Scanner initialization failed";
break;
msg = L"Frame is corrupted";
break;
msg = L"Frame reconstruction failed";
break;
msg = L"Frame registration failed";
break;
msg = L"Requested operation is unsupported. Check versions";
break;
msg = L"Requested operation is denied. Check your license(s)";
break;
msg = L"Requested operation has failed";
break;
msg = L"Requested operation was canceled from client's side";
break;
msg = L"Unable to start algorithm because input data turned out to be invalid. Please rescan the object.";
break;
default:
msg = L"Unexplained error";
break;
}
std::wcerr << msg << " [error " << std::hex << ec << "] " << "at " << place << std::endl;
}
class SimpleScannerObserver : public asdk::ScannerObserverBase
{
public:
{
switch(button)
{
std::wcout << L"ScannerEvent: trigger button was pressed" << std::endl;
break;
std::wcout << L"ScannerEvent: stop button was pressed" << std::endl;
break;
std::wcout << L"ScannerEvent: record button was pressed" << std::endl;
break;
default:
std::wcout << L"ScannerEvent: unknown button was pressed" << std::endl;
break;
}
}
virtual void deviceOverheated()
{
std::wcout << L"ScannerEvent: device is overheated" << std::endl;
}
virtual void deviceTemperatureBackToNormal()
{
std::wcout << L"ScannerEvent: device temperature is back to normal" << std::endl;
}
virtual void deviceDisconnected()
{
std::wcout << L"ScannerEvent : device was disconnected" << std::endl;
}
};
asdk::ErrorCode createSimpleScannerObserver( asdk::IScannerObserver** observer )
{
*observer = new SimpleScannerObserver();
}
{
std::wcout << L"Looking for scanner..." << std::endl;
{
std::wcout << L"No scanners found" << std::endl;
return errorCode;
}
std::wcout << L"OK" << std::endl;
std::wcout << L"Found scanner with serial number " << scanner->getId()->serial << std::endl;
std::wcout << L"Setting the scanner event handler..." << std::endl;
createSimpleScannerObserver( &observer );
SAFE_SDK_CALL( scanner->setObserver( observer ) );
std::wcout << L"OK" << std::endl;
std::wcout << L"Scanner is ready, press ENTER to start" << std::endl;
std::wcin.setf( ~std::ios::skipws, std::ios::skipws );
std::wcin.get();
std::wcout << L"Creating scanning procedure..." << std::endl;
asdk::ScanningProcedureSettings desc = { 0 };
desc.maxFrameCount = NumberOfFramesToCapture;
desc.pipelineConfiguration =
;
desc.captureTextureFrequency = 10;
desc.ignoreRegistrationErrors = false;
std::wcout << L"OK" << std::endl;
std::wcout << L"Launching scanning procedure in a fully automatic mode..." << std::endl;
SAFE_SDK_CALL(
executeJob( scanning, &workset ) );
std::wcout << L"OK" << std::endl;
std::wcout << L"Preparing workset for further processing..." << std::endl;
std::swap( workset.in, workset.out );
workset.out->clear();
std::wcout << L"OK" << std::endl;
}
asdk::ErrorCode AlgorithmProcessingSample( asdk::AlgorithmWorkset& workset )
{
{
std::wcout << L"Creating serial registration procedure..." << std::endl;
asdk::SerialRegistrationSettings serialDesc = {
};
std::wcout << L"OK" << std::endl;
std::wcout << L"Launching the serial registration algorithm..." << std::endl;
std::wcout << L"OK" << std::endl;
}
std::swap( workset.in, workset.out );
workset.out->clear();
{
std::wcout << L"Creating global registration procedure..." << std::endl;
asdk::GlobalRegistrationSettings globalDesc = {
};
std::wcout << L"OK" << std::endl;
std::wcout << L"Launching the global registration algorithm..." << std::endl;
std::wcout << L"OK" << std::endl;
}
std::swap( workset.in, workset.out );
workset.out->clear();
{
std::wcout << L"Creating outliers removal procedure..." << std::endl;
asdk::OutliersRemovalSettings outliersDesc;
std::wcout << L"OK" << std::endl;
std::wcout << L"Launching the outliers removal algorithm..." << std::endl;
std::wcout << L"OK" << std::endl;
}
std::swap( workset.in, workset.out );
workset.out->clear();
{
std::wcout << L"Creating fast fusion procedure..." << std::endl;
asdk::FastFusionSettings fusionDesc;
fusionDesc.resolution = 2.f;
std::wcout << L"OK" << std::endl;
std::wcout << L"Launching the fast fusion algorithm..." << std::endl;
std::wcout << L"OK" << std::endl;
}
std::wcout << L"Preparing workset for further processing..." << std::endl;
std::swap( workset.in, workset.out );
workset.out->clear();
std::wcout << L"OK" << std::endl;
}
#ifdef ENABLE_TEXTURE_MAPPING
{
{
std::wcout << L"Creating texture mapping procedure..." << std::endl;
asdk::TexturizationSettings textureDesc;
std::wcout << L"OK" << std::endl;
std::wcout << L"Launching the texture mapping algorithm..." << std::endl;
std::wcout << L"OK" << std::endl;
}
std::wcout << L"Preparing workset for further processing..." << std::endl;
std::swap( workset.in, workset.out );
workset.out->clear();
std::wcout << L"OK" << std::endl;
}
#endif
int main( int argc, char **argv )
{
asdk::AlgorithmWorkset workset = { inputContainer, outputContainer, 0, ctSource->getToken(), 0 };
{
std::wcout << L"Finishing work on errors when scanning..." << std::endl;
return (int)errorCode;
}
errorCode = AlgorithmProcessingSample( workset );
{
std::wcout << L"Finishing work on errors when processing..." << std::endl;
return (int)errorCode;
}
#ifdef SAVE_FUSION_MESH_ON
{
asdk::ICompositeContainer* meshContainer = workset.in->getCompositeContainer();
if( meshContainer && meshContainer->getSize() > 0 )
{
asdk::ICompositeMesh* resultMesh = meshContainer->getElement( 0 );
std::wcout << L"Saving the resulting mesh to an OBJ file..." << std::endl;
const wchar_t* filename = OUTPUT_DIR L"\\untextured-mesh.obj";
{
std::wcout << L"Cannot open file '" << filename << L"'" << std::endl;
std::wcout << L"skipped" << std::endl;
}
else
{
std::wcout << L"OK" << std::endl;
}
}
}
{
std::wcout << L"Saving all the reconstructed frames to separate OBJ files..." << std::endl;
for( int ix = 0; ix < workset.in->getSize(); ix++ )
{
for( int jx = 0; jx < scan->getSize(); jx++ )
{
std::wstring pathFormat( OUTPUT_DIR L"\\frame-S%02dF%02d.obj" );
std::vector<wchar_t> pathBuffer( pathFormat.size() +1 );
std::swprintf( pathBuffer.data(), pathBuffer.size(), pathFormat.c_str(), ix, jx );
{
std::wcout << L"Cannot open file '" << pathBuffer.data() << "'" << std::endl;
std::wcout << L"skipped" << std::endl;
break;
}
}
}
{
std::wcout << L"OK" << std::endl;
}
}
#endif
#ifdef ENABLE_TEXTURE_MAPPING
errorCode = TextureProcessingSample( workset );
{
std::wcout << L"failed" << std::endl;
std::wcout << L"Continue to work withstanding errors when texturing..." << std::endl;
}
else
{
#ifdef SAVE_TEXTURED_MESH_ON
{
asdk::ICompositeContainer* meshContainer = workset.in->getCompositeContainer();
if( meshContainer && meshContainer->getSize() > 0 )
{
asdk::ICompositeMesh* resultMesh = meshContainer->getElement( 0 );
std::wcout << L"Saving the resulting textured mesh to an OBJ file..." << std::endl;
const wchar_t* filename = OUTPUT_DIR L"\\textured-mesh.obj";
{
std::wcout << L"Cannot open file '" << filename << "'" << std::endl;
std::wcout << L"skipped" << std::endl;
}
else
{
std::wcout << L"OK" << std::endl;
}
}
}
#endif
}
#endif
{
asdk::ICompositeContainer* meshContainer = workset.in->getCompositeContainer();
if( meshContainer && meshContainer->getSize() > 0 )
{
asdk::ICompositeMesh* resultMesh = meshContainer->getElement( 0 );
std::wcout << L"Showing the resulting mesh..." << std::endl;
SAFE_SDK_CALL( DisplayScene( *resultMesh ) );
std::wcout << L"OK" << std::endl;
}
}
std::wcout << L"Finishing work with capturing library..." << std::endl;
return (int)errorCode;
}