Пример #1
0
void ED_preview_free_dbase(void)
{
	if (G_pr_main)
		free_main(G_pr_main);

	if (G_pr_main_cycles)
		free_main(G_pr_main_cycles);
}
Пример #2
0
static void render_endjob(void *rjv)
{
	RenderJob *rj= rjv;	

	/* this render may be used again by the sequencer without the active 'Render' where the callbacks
	 * would be re-assigned. assign dummy callbacks to avoid referencing freed renderjobs bug [#24508] */
	RE_InitRenderCB(rj->re);

	if(rj->main != G.main)
		free_main(rj->main);

	/* else the frame will not update for the original value */
	if(!(rj->scene->r.scemode & R_NO_FRAME_UPDATE))
		ED_update_for_newframe(G.main, rj->scene, rj->win->screen, 1);
	
	/* XXX above function sets all tags in nodes */
	ntreeClearTags(rj->scene->nodetree);
	
	/* potentially set by caller */
	rj->scene->r.scemode &= ~R_NO_FRAME_UPDATE;
	
	if(rj->srl) {
		NodeTagIDChanged(rj->scene->nodetree, &rj->scene->id);
		WM_main_add_notifier(NC_NODE|NA_EDITED, rj->scene);
	}
	
	/* XXX render stability hack */
	G.rendering = 0;
	WM_main_add_notifier(NC_WINDOW, NULL);
}
Пример #3
0
int BKE_read_file(bContext *C, const char *filepath, ReportList *reports)
{
	BlendFileData *bfd;
	int retval = BKE_READ_FILE_OK;

	if (strstr(filepath, BLENDER_STARTUP_FILE) == NULL) /* don't print user-pref loading */
		printf("read blend: %s\n", filepath);

	bfd = BLO_read_from_file(filepath, reports);
	if (bfd) {
		if (bfd->user) retval = BKE_READ_FILE_OK_USERPREFS;
		
		if (0 == handle_subversion_warning(bfd->main, reports)) {
			free_main(bfd->main);
			MEM_freeN(bfd);
			bfd = NULL;
			retval = BKE_READ_FILE_FAIL;
		}
		else
			setup_app_data(C, bfd, filepath);  // frees BFD
	}
	else
		BKE_reports_prependf(reports, "Loading '%s' failed: ", filepath);
		
	return (bfd ? retval : BKE_READ_FILE_FAIL);
}
Пример #4
0
static void clear_global(void) 
{
//	extern short winqueue_break;	/* screen.c */

	free_main(G.main);          /* free all lib data */
	
//	free_vertexpaint();

	G.main = NULL;
}
Пример #5
0
KX_BlenderSceneConverter::~KX_BlenderSceneConverter()
{
	// clears meshes, and hashmaps from blender to gameengine data
	int i;
	// delete sumoshapes
	

	int numAdtLists = m_map_blender_to_gameAdtList.size();
	for (i=0; i<numAdtLists; i++) {
		BL_InterpolatorList *adtList= *m_map_blender_to_gameAdtList.at(i);

		delete (adtList);
	}

	vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator itw = m_worldinfos.begin();
	while (itw != m_worldinfos.end()) {
		delete (*itw).second;
		itw++;
	}

	vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator itp = m_polymaterials.begin();
	while (itp != m_polymaterials.end()) {
		delete (*itp).second;
		itp++;
	}

	// delete after RAS_IPolyMaterial
	vector<pair<KX_Scene*,BL_Material *> >::iterator itmat = m_materials.begin();
	while (itmat != m_materials.end()) {
		delete (*itmat).second;
		itmat++;
	}	


	vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator itm = m_meshobjects.begin();
	while (itm != m_meshobjects.end()) {
		delete (*itm).second;
		itm++;
	}

#ifdef USE_BULLET
	KX_ClearBulletSharedShapes();
#endif

	/* free any data that was dynamically loaded */
	for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) {
		Main *main= *it;
		free_main(main);
	}

	m_DynamicMaggie.clear();
}
Пример #6
0
/* only to be called on exit blender */
void free_blender(void)
{
	/* samples are in a global list..., also sets G.main->sound->sample NULL */
	free_main(G.main);
	G.main= NULL;

	BKE_spacetypes_free();		/* after free main, it uses space callbacks */
	
	IMB_exit();

	BLI_cb_finalize();

	seq_stripelem_cache_destruct();
	
	free_nodesystem();	
}
Пример #7
0
int main (int argc, char **argv) {

	struct main_pars pars = init_main_pars(argc, argv);
	
	COND_VAR_INIT(sync_barrier);
	MUTEX_INIT(main_lock);
	TRACE_INIT();
	
	run_main(pars);	
	
	free_main(pars);

	TRACE_END();

	return 0;
}
Пример #8
0
/* only read the userdef from a .blend */
int BKE_read_file_userdef(const char *filepath, ReportList *reports)
{
	BlendFileData *bfd;
	int retval = 0;
	
	bfd = BLO_read_from_file(filepath, reports);
	if (bfd->user) {
		retval = BKE_READ_FILE_OK_USERPREFS;
		
		/* only here free userdef themes... */
		BKE_userdef_free();
		
		U = *bfd->user;
		MEM_freeN(bfd->user);
	}
	free_main(bfd->main);
	MEM_freeN(bfd);
	
	return retval;
}
static void render_endjob(void *rjv)
{
	RenderJob *rj = rjv;

	/* this render may be used again by the sequencer without the active 'Render' where the callbacks
	 * would be re-assigned. assign dummy callbacks to avoid referencing freed renderjobs bug [#24508] */
	RE_InitRenderCB(rj->re);

	if (rj->main != G.main)
		free_main(rj->main);

	/* else the frame will not update for the original value */
	if (rj->anim && !(rj->scene->r.scemode & R_NO_FRAME_UPDATE)) {
		/* possible this fails of loading new file while rendering */
		if (G.main->wm.first) {
			ED_update_for_newframe(G.main, rj->scene, 1);
		}
	}
	
	/* XXX above function sets all tags in nodes */
	ntreeCompositClearTags(rj->scene->nodetree);
	
	/* potentially set by caller */
	rj->scene->r.scemode &= ~R_NO_FRAME_UPDATE;
	
	if (rj->srl) {
		nodeUpdateID(rj->scene->nodetree, &rj->scene->id);
		WM_main_add_notifier(NC_NODE | NA_EDITED, rj->scene);
	}

	/* XXX render stability hack */
	G.is_rendering = FALSE;
	WM_main_add_notifier(NC_SCENE | ND_RENDER_RESULT, NULL);

	/* Partial render result will always update display buffer
	 * for first render layer only. This is nice because you'll
	 * see render progress during rendering, but it ends up in
	 * wrong display buffer shown after rendering.
	 *
	 * The code below will mark display buffer as invalid after
	 * rendering in case multiple layers were rendered, which
	 * ensures display buffer matches render layer after
	 * rendering.
	 *
	 * Perhaps proper way would be to toggle active render
	 * layer in image editor and job, so we always display
	 * layer being currently rendered. But this is not so much
	 * trivial at this moment, especially because of external
	 * engine API, so lets use simple and robust way for now
	 *                                          - sergey -
	 */
	if (rj->scene->r.layers.first != rj->scene->r.layers.last) {
		void *lock;
		Image *ima = rj->image;
		ImBuf *ibuf = BKE_image_acquire_ibuf(ima, &rj->iuser, &lock);

		if (ibuf)
			ibuf->userflags |= IB_DISPLAY_BUFFER_INVALID;

		BKE_image_release_ibuf(ima, ibuf, lock);
	}
}
Пример #10
0
void ED_preview_free_dbase(void)
{
	if(pr_main)
		free_main(pr_main);
}
Пример #11
0
/* Note m_map_*** are all ok and don't need to be freed
 * most are temp and NewRemoveObject frees m_map_gameobject_to_blender */
bool KX_BlenderSceneConverter::FreeBlendFile(struct Main *maggie)
{
	int maggie_index= -1;
	int i=0;

	if (maggie==NULL)
		return false;
	
	/* tag all false except the one we remove */
	for (vector<Main*>::iterator it=m_DynamicMaggie.begin(); !(it==m_DynamicMaggie.end()); it++) {
		Main *main= *it;
		if (main != maggie) {
			tag_main(main, 0);
		}
		else {
			maggie_index= i;
		}
		i++;
	}

	/* should never happen but just to be safe */
	if (maggie_index == -1)
		return false;

	m_DynamicMaggie.erase(m_DynamicMaggie.begin() + maggie_index);
	tag_main(maggie, 1);


	/* free all tagged objects */
	KX_SceneList* scenes = m_ketsjiEngine->CurrentScenes();
	int numScenes = scenes->size();


	for (int scene_idx=0;scene_idx<numScenes;scene_idx++)
	{
		KX_Scene* scene = scenes->at(scene_idx);
		if (IS_TAGGED(scene->GetBlenderScene())) {
			RemoveScene(scene); // XXX - not tested yet
			scene_idx--;
			numScenes--;
		}
		else {
			
			/* in case the mesh might be refered to later */
			{
				CTR_Map<STR_HashedString,void*> &mapStringToMeshes = scene->GetLogicManager()->GetMeshMap();
				
				for (int i=0; i<mapStringToMeshes.size(); i++)
				{
					RAS_MeshObject *meshobj= (RAS_MeshObject *) *mapStringToMeshes.at(i);
					if (meshobj && IS_TAGGED(meshobj->GetMesh()))
					{	
						STR_HashedString mn = meshobj->GetName();
						mapStringToMeshes.remove(mn);
						m_map_mesh_to_gamemesh.remove(CHashedPtr(meshobj->GetMesh()));
						i--;
					}
				}
			}

			/* Now unregister actions */
			{
				CTR_Map<STR_HashedString,void*> &mapStringToActions = scene->GetLogicManager()->GetActionMap();

				for (int i=0; i<mapStringToActions.size(); i++)
				{
					ID *action= (ID*) *mapStringToActions.at(i);

					if (IS_TAGGED(action))
					{
						STR_HashedString an = action->name+2;
						mapStringToActions.remove(an);
						i--;
					}
				}
			}
			
			//scene->FreeTagged(); /* removed tagged objects and meshes*/
			CListValue *obj_lists[] = {scene->GetObjectList(), scene->GetInactiveList(), NULL};

			for (int ob_ls_idx=0; obj_lists[ob_ls_idx]; ob_ls_idx++)
			{
				CListValue *obs= obj_lists[ob_ls_idx];
				RAS_MeshObject* mesh;

				for (int ob_idx = 0; ob_idx < obs->GetCount(); ob_idx++)
				{
					KX_GameObject* gameobj = (KX_GameObject*)obs->GetValue(ob_idx);
					if (IS_TAGGED(gameobj->GetBlenderObject())) {

						int size_before = obs->GetCount();

						/* Eventually calls RemoveNodeDestructObject
						 * frees m_map_gameobject_to_blender from UnregisterGameObject */
						scene->RemoveObject(gameobj);

						if (size_before != obs->GetCount())
							ob_idx--;
						else {
							printf("ERROR COULD NOT REMOVE \"%s\"\n", gameobj->GetName().ReadPtr());
						}
					}
					else {
						/* free the mesh, we could be referecing a linked one! */
						int mesh_index= gameobj->GetMeshCount();
						while(mesh_index--) {
							mesh= gameobj->GetMesh(mesh_index);
							if (IS_TAGGED(mesh->GetMesh())) {
								gameobj->RemoveMeshes(); /* XXX - slack, should only remove meshes that are library items but mostly objects only have 1 mesh */
								break;
							}
						}

						/* make sure action actuators are not referencing tagged actions */
						for (unsigned int act_idx=0; act_idx<gameobj->GetActuators().size(); act_idx++)
						{
							if (gameobj->GetActuators()[act_idx]->IsType(SCA_IActuator::KX_ACT_ACTION))
							{
								BL_ActionActuator *act = (BL_ActionActuator*)gameobj->GetActuators()[act_idx];
								if (IS_TAGGED(act->GetAction()))
									act->SetAction(NULL);
							}
						}
					}
				}
			}
		}
	}


	int size;

	// delete the entities of this scene
	/* TODO - */
#if 0
	vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator worldit;
	size = m_worldinfos.size();
	for (i=0, worldit=m_worldinfos.begin(); i<size; ) {
		if ((*worldit).second) {
			delete (*worldit).second;
			*worldit = m_worldinfos.back();
			m_worldinfos.pop_back();
			size--;
		} else {
			i++;
			worldit++;
		}
	}
#endif


	/* Worlds don't reference original blender data so we need to make a set from them */
	typedef std::set<KX_WorldInfo*> KX_WorldInfoSet;
	KX_WorldInfoSet worldset;
	for (int scene_idx=0;scene_idx<numScenes;scene_idx++)
	{
		KX_Scene* scene = scenes->at(scene_idx);
		if (scene->GetWorldInfo())
			worldset.insert( scene->GetWorldInfo() );
	}

	vector<pair<KX_Scene*,KX_WorldInfo*> >::iterator worldit;
	size = m_worldinfos.size();
	for (i=0, worldit=m_worldinfos.begin(); i<size; ) {
		if ((*worldit).second && (worldset.count((*worldit).second)) == 0) {
			delete (*worldit).second;
			*worldit = m_worldinfos.back();
			m_worldinfos.pop_back();
			size--;
		} else {
			i++;
			worldit++;
		}
	}
	worldset.clear();
	/* done freeing the worlds */




	vector<pair<KX_Scene*,RAS_IPolyMaterial*> >::iterator polymit;
	size = m_polymaterials.size();



	for (i=0, polymit=m_polymaterials.begin(); i<size; ) {
		RAS_IPolyMaterial *mat= (*polymit).second;
		Material *bmat= NULL;

		/* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject*)? - Campbell */
		if (mat->GetFlag() & RAS_BLENDERMAT) {
			KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat);
			bmat= bl_mat->GetBlenderMaterial();

		} else {
			KX_PolygonMaterial *kx_mat = static_cast<KX_PolygonMaterial*>(mat);
			bmat= kx_mat->GetBlenderMaterial();
		}

		if (IS_TAGGED(bmat)) {
			/* only remove from bucket */
			((*polymit).first)->GetBucketManager()->RemoveMaterial(mat);
		}

		i++;
		polymit++;
	}



	for (i=0, polymit=m_polymaterials.begin(); i<size; ) {
		RAS_IPolyMaterial *mat= (*polymit).second;
		Material *bmat= NULL;

		/* Why do we need to check for RAS_BLENDERMAT if both are cast to a (PyObject*)? - Campbell */
		if (mat->GetFlag() & RAS_BLENDERMAT) {
			KX_BlenderMaterial *bl_mat = static_cast<KX_BlenderMaterial*>(mat);
			bmat= bl_mat->GetBlenderMaterial();

		} else {
			KX_PolygonMaterial *kx_mat = static_cast<KX_PolygonMaterial*>(mat);
			bmat= kx_mat->GetBlenderMaterial();
		}

		if (bmat) {
			//printf("FOUND MAT '%s' !!! ", ((ID*)bmat)->name+2);
		}
		else {
			//printf("LOST MAT  !!!");
		}

		if (IS_TAGGED(bmat)) {

			delete (*polymit).second;
			*polymit = m_polymaterials.back();
			m_polymaterials.pop_back();
			size--;
			//printf("tagged !\n");
		} else {
			i++;
			polymit++;
			//printf("(un)tagged !\n");
		}
	}

	vector<pair<KX_Scene*,BL_Material*> >::iterator matit;
	size = m_materials.size();
	for (i=0, matit=m_materials.begin(); i<size; ) {
		BL_Material *mat= (*matit).second;
		if (IS_TAGGED(mat->material)) {
			delete (*matit).second;
			*matit = m_materials.back();
			m_materials.pop_back();
			size--;
		} else {
			i++;
			matit++;
		}
	}

	vector<pair<KX_Scene*,RAS_MeshObject*> >::iterator meshit;
	size = m_meshobjects.size();
	for (i=0, meshit=m_meshobjects.begin(); i<size; ) {
		RAS_MeshObject *me= (*meshit).second;
		if (IS_TAGGED(me->GetMesh())) {
			delete (*meshit).second;
			*meshit = m_meshobjects.back();
			m_meshobjects.pop_back();
			size--;
		} else {
			i++;
			meshit++;
		}
	}

	free_main(maggie);

	return true;
}
Пример #12
0
int main(int argc, char** argv)
{
    int i;
    int argc_py_clamped= argc; /* use this so python args can be added after ' - ' */
    bool error = false;
    SYS_SystemHandle syshandle = SYS_GetSystem();
    bool fullScreen = false;
    bool fullScreenParFound = false;
    bool windowParFound = false;
#ifdef WIN32
    bool closeConsole = true;
#endif
    RAS_IRasterizer::StereoMode stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;
    bool stereoWindow = false;
    bool stereoParFound = false;
    int stereoFlag = STEREO_NOSTEREO;
    int domeFov = -1;
    int domeTilt = -200;
    int domeMode = 0;
    char* domeWarp = NULL;
    Text *domeText  = NULL;
    int windowLeft = 100;
    int windowTop = 100;
    int windowWidth = 640;
    int windowHeight = 480;
    GHOST_TUns32 fullScreenWidth = 0;
    GHOST_TUns32 fullScreenHeight= 0;
    int fullScreenBpp = 32;
    int fullScreenFrequency = 60;
    GHOST_TEmbedderWindowID parentWindow = 0;
    bool isBlenderPlayer = false;
    int validArguments=0;
    GHOST_TUns16 aasamples = 0;

#ifdef __linux__
#ifdef __alpha__
    signal (SIGFPE, SIG_IGN);
#endif /* __alpha__ */
#endif /* __linux__ */
    BLI_where_am_i(bprogname, sizeof(bprogname), argv[0]);
#ifdef __APPLE__
    // Can't use Carbon right now because of double defined type ID (In Carbon.h and DNA_ID.h, sigh)
    /*
    IBNibRef 		nibRef;
    WindowRef 		window;
    OSStatus		err;

      // Create a Nib reference passing the name of the nib file (without the .nib extension)
      // CreateNibReference only searches into the application bundle.
      err = ::CreateNibReference(CFSTR("main"), &nibRef);
      if (err) return -1;

    	// Once the nib reference is created, set the menu bar. "MainMenu" is the name of the menu bar
    	// object. This name is set in InterfaceBuilder when the nib is created.
    	err = ::SetMenuBarFromNib(nibRef, CFSTR("MenuBar"));
    	if (err) return -1;

    	  // We don't need the nib reference anymore.
    	  ::DisposeNibReference(nibRef);
    */
#endif // __APPLE__

    // We don't use threads directly in the BGE, but we need to call this so things like
    // freeing up GPU_Textures works correctly.
    BLI_threadapi_init();

    RNA_init();

    init_nodesystem();

    initglobals();

    // We load our own G.main, so free the one that initglobals() gives us
    free_main(G.main);
    G.main = NULL;

    IMB_init();

    // Setup builtin font for BLF (mostly copied from creator.c, wm_init_exit.c and interface_style.c)
    BLF_init(11, U.dpi);
    BLF_lang_init();
    BLF_load_mem("default", (unsigned char*)datatoc_bfont_ttf, datatoc_bfont_ttf_size);

    // Parse command line options
#if defined(DEBUG)
    printf("argv[0] = '%s'\n", argv[0]);
#endif

#ifdef WIN32
    if (scr_saver_init(argc, argv))
    {
        switch (scr_saver_mode)
        {
        case SCREEN_SAVER_MODE_CONFIGURATION:
            MessageBox(scr_saver_hwnd, "This screen saver has no options that you can set", "Screen Saver", MB_OK);
            break;
        case SCREEN_SAVER_MODE_PASSWORD:
        /* This is W95 only, which we currently do not support.
           Fall-back to normal screen saver behaviour in that case... */
        case SCREEN_SAVER_MODE_SAVER:
            fullScreen = true;
            fullScreenParFound = true;
            break;

        case SCREEN_SAVER_MODE_PREVIEW:
            /* This will actually be handled somewhere below... */
            break;
        }
    }
#endif
    // XXX add the ability to change this values to the command line parsing.
    U.mixbufsize = 2048;
    U.audiodevice = 2;
    U.audiorate = 44100;
    U.audioformat = 0x24;
    U.audiochannels = 2;

    // XXX this one too
    U.anisotropic_filter = 2;

    sound_init_once();

    /* if running blenderplayer the last argument can't be parsed since it has to be the filename. */
    isBlenderPlayer = !BLO_is_a_runtime(argv[0]);
    if (isBlenderPlayer)
        validArguments = argc - 1;
    else
        validArguments = argc;

    for (i = 1; (i < validArguments) && !error
#ifdef WIN32
            && scr_saver_mode == SCREEN_SAVER_MODE_NONE
#endif
            ;)

    {
#if defined(DEBUG)
        printf("argv[%d] = '%s'   , %i\n", i, argv[i],argc);
#endif
        if (argv[i][0] == '-')
        {
            /* ignore all args after " - ", allow python to have own args */
            if (argv[i][1]=='\0') {
                argc_py_clamped= i;
                break;
            }

            switch (argv[i][1])
            {
            case 'g':
                // Parse game options
            {
                i++;
                if (i <= validArguments)
                {
                    char* paramname = argv[i];
                    // Check for single value versus assignment
                    if (i+1 <= validArguments && (*(argv[i+1]) == '='))
                    {
                        i++;
                        if (i + 1 <= validArguments)
                        {
                            i++;
                            // Assignment
                            SYS_WriteCommandLineInt(syshandle, paramname, atoi(argv[i]));
                            SYS_WriteCommandLineFloat(syshandle, paramname, atof(argv[i]));
                            SYS_WriteCommandLineString(syshandle, paramname, argv[i]);
#if defined(DEBUG)
                            printf("%s = '%s'\n", paramname, argv[i]);
#endif
                            i++;
                        }
                        else
                        {
                            error = true;
                            printf("error: argument assignment %s without value.\n", paramname);
                        }
                    }
                    else
                    {
//							SYS_WriteCommandLineInt(syshandle, argv[i++], 1);
                    }
                }
            }
            break;

            case 'd':
                i++;
                G.f |= G_DEBUG;     /* std output printf's */
                MEM_set_memory_debug();
                break;

            case 'f':
                i++;
                fullScreen = true;
                fullScreenParFound = true;
                if ((i + 2) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-')
                {
                    fullScreenWidth = atoi(argv[i++]);
                    fullScreenHeight = atoi(argv[i++]);
                    if ((i + 1) <= validArguments && argv[i][0] != '-')
                    {
                        fullScreenBpp = atoi(argv[i++]);
                        if ((i + 1) <= validArguments && argv[i][0] != '-')
                            fullScreenFrequency = atoi(argv[i++]);
                    }
                }
                break;
            case 'w':
                // Parse window position and size options
                i++;
                fullScreen = false;
                windowParFound = true;

                if ((i + 2) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-')
                {
                    windowWidth = atoi(argv[i++]);
                    windowHeight = atoi(argv[i++]);
                    if ((i + 2) <= validArguments && argv[i][0] != '-' && argv[i+1][0] != '-')
                    {
                        windowLeft = atoi(argv[i++]);
                        windowTop = atoi(argv[i++]);
                    }
                }
                break;

            case 'h':
                usage(argv[0], isBlenderPlayer);
                return 0;
                break;
            case 'i':
                i++;
                if ( (i + 1) <= validArguments )
                    parentWindow = atoi(argv[i++]);
                else {
                    error = true;
                    printf("error: too few options for parent window argument.\n");
                }
#if defined(DEBUG)
                printf("XWindows ID = %d\n", parentWindow);
#endif // defined(DEBUG)
                break;
            case 'm':
                i++;
                if ((i+1) <= validArguments )
                    aasamples = atoi(argv[i++]);
                break;
            case 'c':
                i++;
#ifdef WIN32
                closeConsole = false;
#endif
                break;
            case 's':  // stereo
                i++;
                if ((i + 1) <= validArguments)
                {
                    stereomode = (RAS_IRasterizer::StereoMode) atoi(argv[i]);
                    if (stereomode < RAS_IRasterizer::RAS_STEREO_NOSTEREO || stereomode >= RAS_IRasterizer::RAS_STEREO_MAXSTEREO)
                        stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;

                    if(!strcmp(argv[i], "nostereo"))  // ok, redundant but clear
                        stereomode = RAS_IRasterizer::RAS_STEREO_NOSTEREO;

                    // only the hardware pageflip method needs a stereo window
                    else if(!strcmp(argv[i], "hwpageflip")) {
                        stereomode = RAS_IRasterizer::RAS_STEREO_QUADBUFFERED;
                        stereoWindow = true;
                    }
                    else if(!strcmp(argv[i], "syncdoubling"))
                        stereomode = RAS_IRasterizer::RAS_STEREO_ABOVEBELOW;

                    else if(!strcmp(argv[i], "anaglyph"))
                        stereomode = RAS_IRasterizer::RAS_STEREO_ANAGLYPH;

                    else if(!strcmp(argv[i], "sidebyside"))
                        stereomode = RAS_IRasterizer::RAS_STEREO_SIDEBYSIDE;

                    else if(!strcmp(argv[i], "vinterlace"))
                        stereomode = RAS_IRasterizer::RAS_STEREO_VINTERLACE;

#if 0
                    // future stuff
                    else if(!strcmp(argv[i], "stencil")
                            stereomode = RAS_STEREO_STENCIL;
#endif

                            i++;
                            stereoParFound = true;
                            stereoFlag = STEREO_ENABLED;
                }
            else
            {
                error = true;
                printf("error: too few options for stereo argument.\n");
                }
                break;
            case 'D':
                stereoFlag = STEREO_DOME;
                stereomode = RAS_IRasterizer::RAS_STEREO_DOME;
                i++;
                if ((i + 1) <= validArguments)
                {
                    if(!strcmp(argv[i], "angle")) {
                        i++;
                        domeFov = atoi(argv[i++]);
                    }
                    if(!strcmp(argv[i], "tilt")) {
                        i++;
                        domeTilt = atoi(argv[i++]);
                    }
                    if(!strcmp(argv[i], "warpdata")) {
                        i++;
                        domeWarp = argv[i++];
                    }
                    if(!strcmp(argv[i], "mode")) {
                        i++;
                        if(!strcmp(argv[i], "fisheye"))
                            domeMode = DOME_FISHEYE;

                        else if(!strcmp(argv[i], "truncatedfront"))
                            domeMode = DOME_TRUNCATED_FRONT;

                        else if(!strcmp(argv[i], "truncatedrear"))
                            domeMode = DOME_TRUNCATED_REAR;

                        else if(!strcmp(argv[i], "cubemap"))
                            domeMode = DOME_ENVMAP;

                        else if(!strcmp(argv[i], "sphericalpanoramic"))
                            domeMode = DOME_PANORAM_SPH;

                        else
                            printf("error: %s is not a valid dome mode.\n", argv[i]);
                    }
                    i++;
                }
                break;
            default:
                printf("Unknown argument: %s\n", argv[i++]);
                break;
            }
        }