コード例 #1
0
bool FileMessageHandler::ReadFile(const list<Path>& lps, POVMS_Object& msg, POVMS_Object& result)
{
	Path path(FindFilePath(lps, Path(msg.GetUCS2String(kPOVAttrib_ReadFile))));

	if(path.Empty() == false)
		result.SetUCS2String(kPOVAttrib_LocalFile, path().c_str());

	return (path.Empty() == false);
}
コード例 #2
0
ファイル: scene.cpp プロジェクト: wfpokorny/povray
void Scene::SendStatistics(TaskQueue&)
{
    POVMS_Message parserStats(kPOVObjectClass_ParserStatistics, kPOVMsgClass_SceneOutput, kPOVMsgIdent_ParserStatistics);

    GetStatistics(parserStats);

    parserStats.SetInt(kPOVAttrib_SceneId, sceneData->sceneId);
    parserStats.SetSourceAddress(sceneData->backendAddress);
    parserStats.SetDestinationAddress(sceneData->frontendAddress);

    POVMS_SendMessage(parserStats);

    for(std::vector<TraceThreadData*>::iterator i(sceneThreadData.begin()); i != sceneThreadData.end(); i++)
        delete (*i);
    sceneThreadData.clear();
}
コード例 #3
0
void ParserMessageHandler::DebugInfo(Console *console, POVMS_Object& obj, bool conout)
{
    if(conout == true)
    {
        // TODO FIXME HACK
        std::string str(obj.GetString(kPOVAttrib_EnglishText));
        console->Output(str);
    }
}
コード例 #4
0
ファイル: povmscpp.cpp プロジェクト: wfpokorny/povray
void POVMS_List::SetNth(int index, POVMS_Object& item)
{
    int err;

    err = POVMSAttrList_SetNth(&data, index, &item.data);
    if(err != pov_base::kNoErr)
        throw POV_EXCEPTION_CODE(err);

    item.DetachData();
}
コード例 #5
0
ファイル: povmscpp.cpp プロジェクト: wfpokorny/povray
void POVMS_List::Append(POVMS_Object& item)
{
    int err;

    err = POVMSAttrList_Append(&data, &item.data);
    if(err != pov_base::kNoErr)
        throw POV_EXCEPTION_CODE(err);

    item.DetachData();
}
コード例 #6
0
ファイル: povmscpp.cpp プロジェクト: wfpokorny/povray
void POVMS_Object::Set(POVMSType key, POVMS_Object& attr)
{
    int err;

    err = POVMSObject_Set(&data, &attr.data, key);
    if(err != pov_base::kNoErr)
        throw POV_EXCEPTION_CODE(err);

    attr.DetachData();
}
コード例 #7
0
void POVMS_List::Append(POVMS_Object& item)
{
	int err;

	err = POVMSAttrList_Append(&data, &item.data);
	if(err != kNoErr)
		throw err;

	item.DetachData();
}
コード例 #8
0
void POVMS_List::SetNth(int index, POVMS_Object& item)
{
	int err;

	err = POVMSAttrList_SetNth(&data, index, &item.data);
	if(err != kNoErr)
		throw err;

	item.DetachData();
}
コード例 #9
0
void POVMS_Object::Set(POVMSType key, POVMS_Object& attr)
{
	int err;

	err = POVMSObject_Set(&data, &attr.data, key);
	if(err != kNoErr)
		throw err;

	attr.DetachData();
}
コード例 #10
0
ファイル: povmscpp.cpp プロジェクト: wfpokorny/povray
POVMS_Object::POVMS_Object(const POVMS_Object& source)
{
    if(source.IsNull() == false)
    {
        int err;

        err = POVMSObject_Copy(&source.data, &data);
        if(err != pov_base::kNoErr)
            throw POV_EXCEPTION_CODE(err);
    }
}
コード例 #11
0
ファイル: shelloutprocessing.cpp プロジェクト: atlaste/povray
ShelloutAction::ShelloutAction(const ShelloutProcessing *sp, unsigned int attribID, POVMS_Object& opts): returnAction(ignore), returnNegate(false), isSet(false)
{
    if (opts.Exist(attribID))
    {
        POVMS_Object attr;

        opts.Get(attribID, attr);
        if (attr.Exist(kPOVAttrib_CommandString))
        {
            rawCommand = attr.GetString(kPOVAttrib_CommandString);
            if (sp->ExtractCommand(rawCommand, command, rawParameters))
            {
                int action = attr.TryGetInt(kPOVAttrib_ReturnAction, (int) ignore);
                switch (tolower(action))
                {
                case ignore:
                case skipOne:
                case skipAll:
                case quit:
                case abort:
                case fatal:
                    returnAction = (Action) tolower(action);
                    returnNegate = isupper(action);
                    isSet = true;
                    break;

                default:
                    break;
                }
            }
        }
    }
}
コード例 #12
0
void ParserMessageHandler::Progress(Console *console, POVMS_Object& obj, bool verbose)
{
    std::ostringstream sstr;

    switch(obj.GetType(kPOVMSObjectClassID))
    {
        case kPOVObjectClass_ParserProgress:
        {
            sstr << Message2Console::GetProgressTime(obj, kPOVAttrib_RealTime)
                 << " Parsing " << (obj.GetLong(kPOVAttrib_CurrentTokenCount) / (POVMSLong)(1000)) << "K tokens\r";
            break;
        }
        case kPOVObjectClass_BoundingProgress:
        {
            sstr << Message2Console::GetProgressTime(obj, kPOVAttrib_RealTime)
                 << " Bounding " << (obj.GetLong(kPOVAttrib_CurrentNodeCount) / (POVMSLong)(1000)) << "K nodes\r";
            break;
        }
    }

    console->Output(sstr.str());
}
コード例 #13
0
bool FileMessageHandler::FindFile(const list<Path>& lps, POVMS_Object& msg, POVMS_Object& result)
{
	POVMS_List files;
	Path path;

	msg.Get(kPOVAttrib_ReadFile, files);

	for(int i = 1; i <= files.GetListSize(); i++)
	{
		POVMS_Attribute attr;

		files.GetNth(i, attr);

		path = FindFilePath(lps, Path(attr.GetUCS2String()));

		if(path.Empty() == false)
			break;
	}

	result.SetUCS2String(kPOVAttrib_ReadFile, path().c_str());

	return (path.Empty() == false);
}
コード例 #14
0
void RenderMessageHandler::Progress(Console *console, POVMS_Object& obj, bool verbose)
{
	ostringstream sstr;

	switch(obj.GetType(kPOVMSObjectClassID))
	{
		case kPOVObjectClass_PhotonProgress:
		{
			int cpc(obj.GetInt(kPOVAttrib_CurrentPhotonCount));

			sstr << Message2Console::GetProgressTime(obj, kPOVAttrib_RealTime)
			     << " Photons " << cpc << "    \r";
			break;
		}
		case kPOVObjectClass_RadiosityProgress:
		{
			int pt(obj.GetInt(kPOVAttrib_Pixels));
			int pc(obj.GetInt(kPOVAttrib_PixelsCompleted));
			int percent = 0;

			if(pt > 0)
				percent = (pc * 100) / pt;

			sstr << Message2Console::GetProgressTime(obj, kPOVAttrib_RealTime)
			     << " Radiosity pretrace completed " << pc << " of " << pt << " pixels (" << percent << "%)    \r";
			break;
		}
		case kPOVObjectClass_RenderProgress:
		{
			int pt(obj.GetInt(kPOVAttrib_Pixels));
			int pp(obj.GetInt(kPOVAttrib_PixelsPending));
			int pc(obj.GetInt(kPOVAttrib_PixelsCompleted));
			int percent = 0;

			if(pt > 0)
				percent = (pc * 100) / pt;

			sstr << Message2Console::GetProgressTime(obj, kPOVAttrib_RealTime)
			     << "Rendering completed " << pc << " of " << pt << " pixels (" << percent << "%) and " << pp << " pixels pending    \r";
			break;
		}
	}

	console->Output(sstr.str());
}
コード例 #15
0
ファイル: vfecontrol.cpp プロジェクト: UberPOV/UberPOV
// Sets the options to be used on the next render. Accepts a vfeRenderOptions
// instance as its only parameter, and returns any one of a number of possible
// error codes (and sets m_LastError), as documented below:
//
//   vfeFailedToInitObject           - this is an internal error
//   vfeFailedToSetMaxThreads        - self-explanatory
//   vfeFailedToParseINI             - an INI file specified could not be parsed
//   vfeFailedToSetSource            - the source file specified could not be set
//   vfeFailedToParseCommand         - a command-line option was invalid
//   vfeNoInputFile                  - no input file specified either directly or via INI
//   vfeRenderBlockSizeTooSmall      - self-explanatory
//   vfeFailedToWriteINI             - a request to write the render options to an INI file failed
//   vfeUnsupportedOptionCombination - unsupported option combination
//
// If vfeRenderOptions explicitly specifies a source file, it will override
// any set via a parsed INI file. Furthermore, any source file set via a
// command-line option overrides both of the above.
//
// Note that it is your responsibility to add any default INI files that should
// be processed to the INI file list; neither SetOptions() nor any other part
// of the VFE or POV-Ray code will do that for you. This includes non-platform
// specific files such as a potential povray.ini in the CWD.
int vfeSession::SetOptions (vfeRenderOptions& opts)
{
  int                     err;
  UCS2                    str [MAX_PATH];
  POVMSObject             obj;
  vfeProcessRenderOptions options(this);

  m_OutputToFileSet = false;
  m_UsingAlpha = false;
  m_RenderingAnimation = false;
  m_RealTimeRaytracing = false;
  m_ClocklessAnimation = false;
  m_RenderWidth = m_RenderHeight = 0;
  ClearOptions();

  if ((err = POVMSObject_New (&obj, kPOVObjectClass_RenderOptions)) != kNoErr)
    return (m_LastError = vfeFailedToInitObject) ;

  if ((err = POVMSUtil_SetInt (&obj, kPOVAttrib_MaxRenderThreads, opts.m_ThreadCount)) != kNoErr)
    return (m_LastError = vfeFailedToSetMaxThreads) ;

  // we set this here for potential use by the IO permissions path checking code
  m_InputFilename = opts.m_SourceFile;

  // most likely povray.ini will be the first INI file processed here (as it's included by default)
  for (vector<UCS2String>::iterator i = opts.m_IniFiles.begin(); i != opts.m_IniFiles.end(); i++)
  {
    // we call TestAccessAllowed() here, even though ParseFile() will do it also, since if
    // access is denied, the reason will not be obvious (ParseFile() just returns kCannotOpenFileErr).
    if (!TestAccessAllowed (Path(*i), false))
      return (m_LastError = vfeIORestrictionDeny);

    if ((err = options.ParseFile (UCS2toASCIIString(*i).c_str(), &obj)) != kNoErr)
      return (m_LastError = vfeFailedToParseINI) ;

    // we keep this up to date since the IO permissions feature will use the current input
    // filename to determine the path for default read/write permission in the scene dir.
    int n = sizeof (str) ;
    if ((err = POVMSUtil_GetUCS2String (&obj, kPOVAttrib_InputFile, str, &n)) == kNoErr)
      if (m_InputFilename != str)
        m_InputFilename = str;
  }

  // m_SourceFile overrides any source file set by the INI files
  if (opts.m_SourceFile.empty() == false)
  {
    m_InputFilename = opts.m_SourceFile;
    if ((err = POVMSUtil_SetUCS2String (&obj, kPOVAttrib_InputFile, opts.m_SourceFile.c_str())) != kNoErr)
      return (m_LastError = vfeFailedToSetSource);
  }

  // any source file set on the command-line overrides a source file set another way
  for (vector<string>::iterator i = opts.m_Commands.begin(); i != opts.m_Commands.end(); i++)
  {
    if ((err = options.ParseString (i->c_str(), &obj)) != kNoErr)
      return (m_LastError = vfeFailedToParseCommand) ;
    int n = sizeof (str) ;
    if ((err = POVMSUtil_GetUCS2String (&obj, kPOVAttrib_InputFile, str, &n)) == kNoErr)
      if (m_InputFilename != str)
        m_InputFilename = str;
  }

  int n = sizeof (str) ;
  if ((err = POVMSUtil_GetUCS2String (&obj, kPOVAttrib_InputFile, str, &n)) != kNoErr)
    return (m_LastError = vfeNoInputFile);
  m_InputFilename = str;

  POVMSUtil_GetInt (&obj, kPOVAttrib_Width, &m_RenderWidth) ;
  POVMSUtil_GetInt (&obj, kPOVAttrib_Height, &m_RenderHeight) ;

  std::list<Path> libpaths;
  POVMS_Object ropts (obj) ;
  if (ropts.Exist (kPOVAttrib_LibraryPath))
  {
    POVMS_List pathlist;
    ropts.Get (kPOVAttrib_LibraryPath, pathlist) ;

    // we take the opportunity to remove any duplicates that are in the path list.
    // it's cleaner to do that here, rather than in the INI parser, since it's table-
    // driven and doesn't have an explicit function for adding library paths per se.
    //
    // we use the Path equivalence operator rather than a string compare since
    // using Path should handle platform-specific issues like case-sensitivity (or,
    // rather, lack thereof). note that at the time of writing, the Path class did
    // not yet implement case-insensitive comparisions.
    //
    // NB while it would of course be more efficient to sort the list so searches are
    // faster, we'd have to make a copy of it to do that, as we can't change the order
    // of existing entries (that would change the include path search order). it's not
    // common to have a lot of include paths, so we just use linear searches.
    for (int i = 1; i <= pathlist.GetListSize(); i++)
    {
      POVMS_Attribute lp;

      pathlist.GetNth(i, lp);
      Path path(lp.GetUCS2String());
      if (find(libpaths.begin(), libpaths.end(), path) == libpaths.end())
        libpaths.push_back(path);
    }
  }

  if (opts.m_LibraryPaths.empty() == false)
  {
    for (vector<UCS2String>::const_iterator i = opts.m_LibraryPaths.begin(); i != opts.m_LibraryPaths.end(); i++)
    {
      Path path(*i);

      if (find(libpaths.begin(), libpaths.end(), path) == libpaths.end())
        libpaths.push_back(path);
    }
  }

  if (libpaths.empty() == false)
  {
    POVMS_List pathlist;
    for (list<Path>::iterator i = libpaths.begin(); i != libpaths.end(); i++)
    {
      POVMS_Attribute attr((*i)().c_str());
      pathlist.Append(attr);
    }
    ropts.Set (kPOVAttrib_LibraryPath, pathlist) ;
  }

  if (ropts.TryGetBool(kPOVAttrib_RealTimeRaytracing, false) == true)
    ropts.SetBool(kPOVAttrib_OutputToFile, false);

  m_OutputToFileSet = ropts.TryGetBool(kPOVAttrib_OutputToFile, true);

  // this is a bit messy: Grayscale_Output or OutputAlpha may be specified
  // in an INI file or elsewhere prior to the output file type being set.
  // so we can't check to see if it is supported with that file type
  // until all options have been parsed.
  if (m_OutputToFileSet)
  {
    int oft = ropts.TryGetInt(kPOVAttrib_OutputFileType, DEFAULT_OUTPUT_FORMAT);
    bool has16BitGrayscale = false;
    bool hasAlpha = false;
    for (int i = 0; FileTypeTable[i].internalId != 0; i ++)
    {
      if (oft == FileTypeTable[i].internalId)
      {
        has16BitGrayscale = FileTypeTable[i].has16BitGrayscale;
        hasAlpha          = FileTypeTable[i].hasAlpha;
        break;
      }
    }
    if (ropts.TryGetBool(kPOVAttrib_GrayscaleOutput, false) && !has16BitGrayscale)
    {
      AppendStatusMessage ("Grayscale output not currently supported with selected output file type.");
      AppendErrorMessage ("Grayscale output not currently supported with selected output file type.") ;
      return (m_LastError = vfeUnsupportedOptionCombination);
    }
    if (ropts.TryGetBool(kPOVAttrib_OutputAlpha, false) && !hasAlpha)
    {
      AppendWarningMessage ("Warning: Alpha channel output currently not (or not officially) supported with selected output file type.") ;
    }
  }

  if (ropts.TryGetInt(kPOVAttrib_RenderBlockSize, 32) < 4)
    return (m_LastError = vfeRenderBlockSizeTooSmall);

  if ((ropts.TryGetInt(kPOVAttrib_DisplayGammaType, DEFAULT_DISPLAY_GAMMA_TYPE) == kPOVList_GammaType_PowerLaw) &&
      (ropts.TryGetFloat(kPOVAttrib_DisplayGamma, DEFAULT_DISPLAY_GAMMA) < 0.001f))
    return (m_LastError = vfeDisplayGammaTooSmall);
  if ((ropts.TryGetInt(kPOVAttrib_FileGammaType, DEFAULT_FILE_GAMMA_TYPE) == kPOVList_GammaType_PowerLaw) &&
      (ropts.TryGetFloat(kPOVAttrib_FileGamma, DEFAULT_FILE_GAMMA) < 0.001f))
    return (m_LastError = vfeFileGammaTooSmall);

  n = sizeof (str) ;
  if ((err = POVMSUtil_GetUCS2String (&obj, kPOVAttrib_CreateIni, str, &n)) == kNoErr && str [0] != 0)
    if ((err = options.WriteFile (UCS2toASCIIString(str).c_str(), &obj)) != kNoErr)
      return (m_LastError = vfeFailedToWriteINI);

  opts.m_Options = ropts;
  m_RenderOptions = opts ;
  m_OptionsSet = true;

  return (m_LastError = vfeNoError) ;
}
コード例 #16
0
ファイル: scene.cpp プロジェクト: wfpokorny/povray
void Scene::StartParser(POVMS_Object& parseOptions)
{
    size_t seed = 0; // TODO

    // A scene can only be parsed once
    if (parserControlThread == nullptr)
        parserControlThread = new std::thread(boost::bind(&Scene::ParserControlThread, this));
    else
        return;

    if (parseOptions.Exist(kPOVAttrib_Version))
    {
        sceneData->languageVersion = clip(int(parseOptions.GetFloat(kPOVAttrib_Version) * 100.0f + .5f), 100, 10000);
        sceneData->languageVersionSet = true;
    }

    sceneData->warningLevel = clip(parseOptions.TryGetInt(kPOVAttrib_WarningLevel, 9), 0, 9);

    sceneData->inputFile = parseOptions.TryGetUCS2String(kPOVAttrib_InputFile, "object.pov");
    sceneData->headerFile = parseOptions.TryGetUCS2String(kPOVAttrib_IncludeHeader, "");

    DBL outputWidth  = parseOptions.TryGetFloat(kPOVAttrib_Width, 160);
    DBL outputHeight = parseOptions.TryGetFloat(kPOVAttrib_Height, 120);
    sceneData->aspectRatio = outputWidth / outputHeight;

    sceneData->defaultFileType = parseOptions.TryGetInt(kPOVAttrib_OutputFileType, DEFAULT_OUTPUT_FORMAT); // TODO - should get DEFAULT_OUTPUT_FORMAT from the front-end
    sceneData->clocklessAnimation = parseOptions.TryGetBool(kPOVAttrib_ClocklessAnimation, false); // TODO - experimental code

    sceneData->splitUnions = parseOptions.TryGetBool(kPOVAttrib_SplitUnions, false);
    sceneData->removeBounds = parseOptions.TryGetBool(kPOVAttrib_RemoveBounds, true);
    sceneData->boundingMethod = clip<int>(parseOptions.TryGetInt(kPOVAttrib_BoundingMethod, 1), 1, 2);
    if(parseOptions.TryGetBool(kPOVAttrib_Bounding, true) == false)
        sceneData->boundingMethod = 0;

    sceneData->outputAlpha = parseOptions.TryGetBool(kPOVAttrib_OutputAlpha, false);
    if (!sceneData->outputAlpha)
        // if we're not outputting an alpha channel, precompose the scene background against a black "background behind the background"
        // (NB: Here, background color is still at its default of <0,0,0,0,1> = full transparency; we're changing that to opaque black.)
        sceneData->backgroundColour.Clear();

    // NB a value of '0' for any of the BSP parameters tells the BSP code to use its internal default
    sceneData->bspMaxDepth = parseOptions.TryGetInt(kPOVAttrib_BSP_MaxDepth, 0);
    sceneData->bspObjectIsectCost = clip<float>(parseOptions.TryGetFloat(kPOVAttrib_BSP_ISectCost, 0.0f), 0.0f, HUGE_VAL);
    sceneData->bspBaseAccessCost = clip<float>(parseOptions.TryGetFloat(kPOVAttrib_BSP_BaseAccessCost, 0.0f), 0.0f, HUGE_VAL);
    sceneData->bspChildAccessCost = clip<float>(parseOptions.TryGetFloat(kPOVAttrib_BSP_ChildAccessCost, 0.0f), 0.0f, HUGE_VAL);
    sceneData->bspMissChance = clip<float>(parseOptions.TryGetFloat(kPOVAttrib_BSP_MissChance, 0.0f), 0.0f, 1.0f - EPSILON);

    sceneData->realTimeRaytracing = parseOptions.TryGetBool(kPOVAttrib_RealTimeRaytracing, false);

    if(parseOptions.Exist(kPOVAttrib_Declare) == true)
    {
        POVMS_List ds;

        parseOptions.Get(kPOVAttrib_Declare, ds);
        for(int i = 1; i <= ds.GetListSize(); i++)
        {
            std::ostringstream sstr;
            POVMS_Attribute a;
            POVMS_Object d;

            ds.GetNth(i, d);
            d.Get(kPOVAttrib_Value, a);
            switch (a.Type())
            {
                case kPOVMSType_CString:
                    sstr << "\"" + d.TryGetString(kPOVAttrib_Value, "") + "\"";
                    break;

                case kPOVMSType_Float:
                    sstr << d.TryGetFloat(kPOVAttrib_Value, 0.0);
                    break;

                default:
                    // shouldn't happen unless we make a coding error
                    throw POV_EXCEPTION(kParamErr, "Invalid type passed in declare list");
            }

            sceneData->declaredVariables.insert(make_pair(d.GetString(kPOVAttrib_Identifier), sstr.str()));
        }
    }

    // do parsing
    sceneThreadData.push_back(dynamic_cast<TraceThreadData *>(parserTasks.AppendTask(new ParserTask(
        sceneData, pov_parser::ParserOptions(bool(parseOptions.Exist(kPOVAttrib_Clock)), parseOptions.TryGetFloat(kPOVAttrib_Clock, 0.0), seed)
        ))));

    // wait for parsing
    parserTasks.AppendSync();

    // do bounding - we always call this even if the bounding is turned off
    // because it also generates object statistics
    sceneThreadData.push_back(dynamic_cast<TraceThreadData *>(parserTasks.AppendTask(new BoundingTask(
        sceneData,
        clip<int>(parseOptions.TryGetInt(kPOVAttrib_BoundingThreshold, DEFAULT_AUTO_BOUNDINGTHRESHOLD),1,SIGNED16_MAX),
        seed
        ))));

    // wait for bounding
    parserTasks.AppendSync();

    // wait for bounding to finish
    parserTasks.AppendSync();

    // send statistics
    parserTasks.AppendFunction(boost::bind(&Scene::SendStatistics, this, _1));

    // send done message and compatibility data
    parserTasks.AppendFunction(boost::bind(&Scene::SendDoneMessage, this, _1));
}
コード例 #17
0
ファイル: scene.cpp プロジェクト: wfpokorny/povray
void Scene::GetStatistics(POVMS_Object& parserStats)
{
    struct TimeData final
    {
        POV_LONG cpuTime;
        POV_LONG realTime;
        size_t samples;

        TimeData() : cpuTime(0), realTime(0), samples(0) { }
    };

    TimeData timeData[TraceThreadData::kMaxTimeType];

    for(std::vector<TraceThreadData*>::iterator i(sceneThreadData.begin()); i != sceneThreadData.end(); i++)
    {
        timeData[(*i)->timeType].realTime = max(timeData[(*i)->timeType].realTime, (*i)->realTime);
        if ((*i)->cpuTime >= 0)
            timeData[(*i)->timeType].cpuTime += (*i)->cpuTime;
        else
            timeData[(*i)->timeType].cpuTime = -1;
        timeData[(*i)->timeType].samples++;
    }

    for(size_t i = TraceThreadData::kUnknownTime; i < TraceThreadData::kMaxTimeType; i++)
    {
        if(timeData[i].samples > 0)
        {
            POVMS_Object elapsedTime(kPOVObjectClass_ElapsedTime);

            elapsedTime.SetLong(kPOVAttrib_RealTime, timeData[i].realTime);
            if (timeData[i].cpuTime >= 0)
                elapsedTime.SetLong(kPOVAttrib_CPUTime, timeData[i].cpuTime);
            elapsedTime.SetInt(kPOVAttrib_TimeSamples, POVMSInt(timeData[i].samples));

            switch(i)
            {
                case TraceThreadData::kParseTime:
                    parserStats.Set(kPOVAttrib_ParseTime, elapsedTime);
                    break;
                case TraceThreadData::kBoundingTime:
                    parserStats.Set(kPOVAttrib_BoundingTime, elapsedTime);
                    break;
            }
        }
    }

    parserStats.SetInt(kPOVAttrib_FiniteObjects, sceneData->numberOfFiniteObjects);
    parserStats.SetInt(kPOVAttrib_InfiniteObjects, sceneData->numberOfInfiniteObjects);
    parserStats.SetInt(kPOVAttrib_LightSources, POVMSInt(sceneData->lightSources.size()));
    parserStats.SetInt(kPOVAttrib_Cameras, POVMSInt(sceneData->cameras.size()));

    if(sceneData->boundingMethod == 2)
    {
        parserStats.SetInt(kPOVAttrib_BSPNodes, sceneData->nodes);
        parserStats.SetInt(kPOVAttrib_BSPSplitNodes, sceneData->splitNodes);
        parserStats.SetInt(kPOVAttrib_BSPObjectNodes, sceneData->objectNodes);
        parserStats.SetInt(kPOVAttrib_BSPEmptyNodes, sceneData->emptyNodes);
        parserStats.SetInt(kPOVAttrib_BSPMaxObjects, sceneData->maxObjects);
        parserStats.SetFloat(kPOVAttrib_BSPAverageObjects, sceneData->averageObjects);
        parserStats.SetInt(kPOVAttrib_BSPMaxDepth, sceneData->maxDepth);
        parserStats.SetFloat(kPOVAttrib_BSPAverageDepth, sceneData->averageDepth);
        parserStats.SetInt(kPOVAttrib_BSPAborts, sceneData->aborts);
        parserStats.SetFloat(kPOVAttrib_BSPAverageAborts, sceneData->averageAborts);
        parserStats.SetFloat(kPOVAttrib_BSPAverageAbortObjects, sceneData->averageAbortObjects);
    }
}