Beispiel #1
0
void PivotSnap::Snap(Object* pobj, IPoint2 *p, TimeValue t)
{	
	// This snap computes the bounding box points of a node as 
	// well as the pivot point

	//local copy of the cursor position
	Point2 fp = Point2((float)p->x, (float)p->y);

	//In this snap mode we actually need to get a pointer to the node so that we 
	// can check for WSM's and compute the pivot point
	INode *inode = theman->GetNode();
	Matrix3 atm(1); //This will hold the nodes tm before WSMs

	//See if this guys has any spacewarps applied
	BOOL wsm = (BOOL) inode->GetProperty(PROPID_HAS_WSM);

	//If it does then we'll need to get a meaningful tm as follows
	if(wsm)
		atm = inode->GetObjTMBeforeWSM(t);

	//get the node's bounding box
	Box3 box;
	box.Init();
	pobj->GetDeformBBox(t, box, NULL );

	if(EssentiallyEmpty(box))
		pobj->GetLocalBoundBox(t, inode, theman->GetVpt() , box);

		//We need a hitmesh which shows the bounding box of the node
	//This automatic variable gets passed to the hitmesh copy constructor
	// in every case
	HitMesh thehitmesh, *phitmesh;
	thehitmesh.setNumVerts(8);
	for(int jj = 0;jj<8;++jj)
		thehitmesh.setVert(jj,box[jj]);


	BOOL got_one= FALSE;

	//Compute all the hit point candidates
	if(	GetActive(PIV_SUB))
	{
		got_one = FALSE;
		Point3 *pivpt;

		//JH 10/02/01
		//DID 296059
		Matrix3 tm(1);
		Point3 pos = inode->GetObjOffsetPos();
		tm.PreTranslate(pos);
		Quat quat = inode->GetObjOffsetRot();
		PreRotateMatrix(tm, quat);
		ScaleValue scale = inode->GetObjOffsetScale();
		ApplyScaling(tm, scale);
		Matrix3 InvTm = Inverse(tm);



		//JH 10/02/01
		//atm contains the identity normally, or the node TM before spacewarps, when space warps are applied
		//We're computing a point relative to the node TM, so in the former case the inverse of
		//the object offset pos is what we want. In the latter (when the node TM is identtity, we must add
		//in the node TM before WSM.
		pivpt = new Point3(atm.GetTrans() + InvTm.GetTrans());

		//Make a hitmesh
		phitmesh = new HitMesh(thehitmesh);

		//now register a hit with the osnap manager
		theman->RecordHit(new OsnapHit(*pivpt, this, PIV_SUB, phitmesh));
	}

	if(	GetActive(BBOX_SUB))
	{

		//set up our highlight mesh
		for(int ii = 0;ii<8;++ii)
		{
			phitmesh = new HitMesh(thehitmesh);

			theman->RecordHit(new OsnapHit(box[ii], this, BBOX_SUB, phitmesh));
		}
	}


};
void PatchDeformPW::ModifyObject(TimeValue t, ModContext &mc, ObjectState * os, INode *incnode) 
{
	Interval iv = FOREVER;

	//TODO: Add the code for actually modifying the object
	//check is local data if not create it
	if (mc.localData == NULL)
		{
		LocalPatchData *localData = new LocalPatchData();
		mc.localData = localData;
		}

	LocalPatchData *localData = (LocalPatchData *)mc.localData;

	if (localData == NULL ) return;

	if (localData->selfNode == NULL)
		{
		localData->selfNode = GetNodeFromModContext(localData);
		}


	//check if patch count has changed if so update our uv space
	//if rebuild then 

	INode *node = NULL;
	pblock->GetValue(pb_patch,t,node,iv);


	if (node == NULL)
		{	
		os->obj->UpdateValidity(GEOM_CHAN_NUM,iv);	
		return;
		}

	ObjectState patchos = node->EvalWorldState(t);
	if ((patchos.obj) && (localData->selfNode))
		{
		iv &= patchos.obj->ObjectValidity(t);

		Matrix3 patchTM = node->GetObjTMBeforeWSM(t, &iv);
		Matrix3 baseTM = localData->selfNode->GetObjTMBeforeWSM(t, &iv);

		PatchObject *patchObj = (PatchObject *) patchos.obj;
		PatchMesh *patch = &patchObj->patch;
		BOOL patchValid = TRUE;
		for (int i =0; i < patch->numPatches; i++)
			{
			if (patch->patches[i].type != PATCH_QUAD)
				{
				patchValid = FALSE;
				}
			}

		if ((!patchValid) && (ip))
			{
			TSTR name;
			name.printf(GetString(IDS_ERROR_TRIPATCH));
			SetWindowText(GetDlgItem(hWnd,IDC_STATUS),name);
			}

		if ((patch->numPatches > 0) && patchValid)
			{
			
			if ( (patch->numPatches != localData->numPatches) ||  (localData->resample))
				{
//rebuild the param data
				BuildParamData(os->obj,localData,patch,patchTM,baseTM);
				
				}
			localData->resample= FALSE;
//setup deformer
			PatchDeformer deformer(localData,patch,baseTM,patchTM);
			os->obj->Deform(&deformer, TRUE);

			}

		}

	os->obj->UpdateValidity(GEOM_CHAN_NUM,iv);
}
Beispiel #3
0
/**
 * This method will be called from the max system when the user
 * has choosen to export to the OpenSceneGraph format.
 * This method is the entry point to the exporter plugin.
 */
int	OSGExp::DoExport(const TCHAR *name, ExpInterface *ei,
					 Interface *i, BOOL suppressPrompts, DWORD MAXOptions){

	// Only support "one at the time" exporting.
	if(isExporting){
		return FALSE;
	}
	isExporting = TRUE;

	// Grab the interface pointer and save it for later use.
	_ip = i;

	// Set export path in options class
	TCHAR p[300];
	TCHAR f[100];
	TCHAR e[10];
	BMMSplitFilename(name, p, f, e);
	_options->setExportPath(p);
	_options->setExportFilename(f);
	_options->setExportExtension(e);

	// Get filename to config file.
	TSTR cfgfilename = _ip->GetDir(APP_PLUGCFG_DIR);;
	cfgfilename += _T("\\OSGEXP.CFG");

	// Load options from config file
	_options->load(cfgfilename);

	// Should we only export selected nodes?
	_onlyExportSelected = (MAXOptions & SCENE_EXPORT_SELECTED) ? TRUE : FALSE;

	// Show option dialog to user and retrive any possible plugin choices.
	if(!suppressPrompts)
		if(!DialogBoxParam(hInstance, MAKEINTRESOURCE(IDD_EXPORTBOX), 
				           GetActiveWindow(), OptionsDlgProc,
						   (LPARAM)_options)){
			// If user closed or canceled export box then shutdown plugin.
			isExporting = FALSE;
			return TRUE;
		}

	// Write options to config file.
	_options->write(cfgfilename);

	// Create OSG root transform to hold the scene.
{	
	osg::ref_ptr<osg::MatrixTransform> rootTransform = new osg::MatrixTransform();
	//osg::MatrixTransform* rootTransform = new osg::MatrixTransform();
	rootTransform->setName(std::string(_ip->GetRootNode()->GetName()));
	// Set static datavariance for better performance
	rootTransform->setDataVariance(osg::Object::STATIC);
	// Set NodeMask
	if(_options->getUseDefaultNodeMaskValue())
		rootTransform->setNodeMask(_options->getDefaultNodeMaskValue());
	osg::Matrix rootMat = getNodeTransform(_ip->GetRootNode(), _ip->GetTime());
	rootTransform->setMatrix(rootMat);
    // Create root stateset for the lights.
	osg::ref_ptr<osg::StateSet> rootStateSet = new osg::StateSet();
	// Turn of lighting if set by the user.
	if(_options->getTurnOffLighting())
		rootStateSet->setMode(GL_LIGHTING,osg::StateAttribute::OVERRIDE|osg::StateAttribute::OFF);
	else
		rootStateSet->setMode(GL_LIGHTING,osg::StateAttribute::ON);
	//osg::StateSet* rootStateSet = new osg::StateSet();
    rootTransform->setStateSet(rootStateSet.get());


	// We will make two progress bars. The first one will show
	// the exporting of materials, wheras the second one will show
	// the exporting of nodes. To get the total number of nodes in the
	// scene graph we will accumulate the total node count while
	// preprocessing the scenegraph for materials.
	_nTotalNodeCount = 0;
	_nCurNode = 0;
	_nTotalMtlCount = _ip->GetSceneMtls()->Count();
	_nCurMtl = 0;

	// Starting up the material exporting progress bar.
	_ip->ProgressStart(_T("Exporting materials..."), TRUE, fn, NULL);
	// Export materials by preprocessing the scenegraph. 
	if(!preProcess(_ip->GetRootNode(), _ip->GetTime())){
		// If user cancels we stop progress bar and return.
		_ip->ProgressEnd();
		isExporting = FALSE;
		return TRUE;
	}
	// We're done exporting materials. Finish the progress bar.
	_ip->ProgressEnd();

	// Starting up the node exporting progress bar.
	_ip->ProgressStart(_T("Exporting scene..."), TRUE, fn, NULL);

	// Get number of children for the root node in the interface.
	int numChildren = _ip->GetRootNode()->NumberOfChildren();
	
	// Call our node enumerator.
	// The nodeEnum function will recurse into itself and 
	// export each object found in the scene.
	for (int idx=0; idx<numChildren; idx++) {
		if (_ip->GetCancel() || !nodeEnum(rootTransform.get(), _ip->GetRootNode()->GetChildNode(idx), rootTransform.get())){
			// If user cancels we stop progress bar and return
			_ip->ProgressEnd();
			isExporting = FALSE;
			return TRUE;
		}
	}
	// Finish exporting progress bar
	_ip->ProgressEnd();


	// If optimize scene graph
	unsigned int optimizeMask = 0;
	if(_options->getTriStripGeometry())
		optimizeMask |= osgUtil::Optimizer::TRISTRIP_GEOMETRY;
	if(_options->getMergeGeometry())
		optimizeMask |= osgUtil::Optimizer::MERGE_GEOMETRY;
	if(_options->getFlattenStaticTransform())
		optimizeMask |= osgUtil::Optimizer::FLATTEN_STATIC_TRANSFORMS;
	if(_options->getShareDuplicateStates())
		optimizeMask |= osgUtil::Optimizer::SHARE_DUPLICATE_STATE;
	if(_options->getSpatializeGroups())
		optimizeMask |= osgUtil::Optimizer::SPATIALIZE_GROUPS;
	if(optimizeMask){
		_ip->ProgressStart(_T("Optimizing scenegraph..."), FALSE, fn, NULL);
		_ip->ProgressUpdate(0.5f); 
		osgUtil::Optimizer optimizer;
		optimizer.optimize(rootTransform.get(), optimizeMask);
		_ip->ProgressEnd();
	}
	 
	// Save file to disk.
	if(_options->getSaveFile()){
		_ip->ProgressStart(_T("Writing file..."), FALSE, fn, NULL);
		_ip->ProgressUpdate(0.5f); 
		if(_options->getExportExtension().compare(".osg")==0 ||
		   _options->getExportExtension().compare(".OSG")==0 ||
		   _options->getExportExtension().compare(".ive")==0 ||
		   _options->getExportExtension().compare(".IVE")==0   ){

			std::string filename(name);

			// Exclude image data from ive file if this options has been choosen
			if(!_options->getIncludeImageDataInIveFile()){
				osgDB::ReaderWriter::Options* opt = new osgDB::ReaderWriter::Options("noTexturesInIVEFile");
				osgDB::Registry::instance()->setOptions(opt);
			}


#if defined(OPENSCENEGRAPH_MAJOR_VERSION) && OPENSCENEGRAPH_MAJOR_VERSION >= 2 && defined(OPENSCENEGRAPH_MINOR_VERSION) && OPENSCENEGRAPH_MINOR_VERSION >= 4
            osgDB::ReaderWriter::WriteResult res = 
               osgDB::Registry::instance()->writeNode(*rootTransform, filename, NULL);
#else
            osgDB::ReaderWriter::WriteResult res = 
               osgDB::Registry::instance()->writeNode(*rootTransform, filename);
#endif

			if(res.error() && _options->getShowErrMsg()){
				static TCHAR szBuffer[256];
				wsprintf(szBuffer,TEXT("Error writing file %s:\n%s"), 
					     TEXT(filename.c_str()),res.message());
				MessageBox (GetActiveWindow(), szBuffer, TEXT("Warning"),
					        MB_OK | MB_ICONWARNING) ;
			}

			if(!_options->getIncludeImageDataInIveFile()){
                // Turn readerwriter options off again.
				osgDB::ReaderWriter::Options* opt = new osgDB::ReaderWriter::Options();
				osgDB::Registry::instance()->setOptions(opt);
            }
		}
		else{
			if(_options->getShowErrMsg()){
				std::string error("Can not find plugin to save file: ");
				error.append(name);
				MessageBox (GetActiveWindow(), error.c_str() , TEXT("Warning"), MB_OK | MB_ICONWARNING) ;
			}
		}
		_ip->ProgressEnd();
	}

	// Show quick preview
	if(_options->getQuickView()){

		float fNear = 1.0f;
		float fFar = 1000.0f;

		// Get the active viewport and the win32 window within it.
		// The position and size will be retreive from this.
		ViewExp* viewExp = _ip->GetActiveViewport();
		float fov = viewExp->GetFOV();
		HWND hWnd = viewExp->getGW()->getHWnd();
		RECT sRect;
		BOOL ok = GetWindowRect(hWnd, &sRect);
		int width = 100;
		int height = 100;
		int x =100;
		int y =100;
		if(ok){
			x = sRect.left;
			y = sRect.top;
			width = sRect.right - sRect.left;
			height = sRect.bottom - sRect.top;
		}

		// Create previewer window and set size.
		Previewer previewer;
		previewer.setWindowSize(x, y, width, height);


		// The affine TM transforms from world coords to view coords
		// so we need the inverse of this matrix
		Matrix3 aTM, camTM, coordSysTM;
		Point3 viewDir, viewPos, lookAtPos, upVector;
		INode* camera;
		float dist = 100;

		Point3 upperLeft = viewExp->MapScreenToView(IPoint2(0, 0), fFar);
		Point3 lowerRight = viewExp->MapScreenToView(IPoint2(width, height), fFar);
		
		viewExp->GetAffineTM(aTM);
		coordSysTM = Inverse(aTM);	

		viewDir = coordSysTM.VectorTransform(Point3(0.0f, 0.0f, -1.0f));
		viewPos = coordSysTM.GetRow(3);
		lookAtPos = viewPos + viewDir;
		upVector.Set(0.0f, 0.0f, 1.0f);

		switch(viewExp->GetViewType()){
			case VIEW_ISO_USER:
			case VIEW_PERSP_USER:
				previewer.setProjectionMatrixAsFrustum(lowerRight.x, upperLeft.x,  upperLeft.y, lowerRight.y, fFar, -fFar);
				break;
			case VIEW_CAMERA:
				previewer.setProjectionMatrixAsFrustum(upperLeft.x, lowerRight.x, lowerRight.y, upperLeft.y, fFar, -fFar);
				camera = viewExp->GetViewCamera();
				camTM = camera->GetObjTMBeforeWSM(_ip->GetTime());
				viewDir = camTM.VectorTransform(Point3(0.0f, 0.0f, -1.0f));
				viewPos = camTM.GetRow(3);
				lookAtPos = viewPos + viewDir;
				break;
			case VIEW_LEFT:
			case VIEW_RIGHT:
			case VIEW_TOP:
			case VIEW_BOTTOM:
			case VIEW_FRONT:
			case VIEW_BACK:
				previewer.setProjectionMatrixAsOrtho(upperLeft.x, lowerRight.x, lowerRight.y, upperLeft.y, -fFar, fFar);
				//cam->setOrtho(upperLeft.x, lowerRight.x, lowerRight.y, upperLeft.y, -fFar, fFar);
				// Go far away from the viewing point in the negative viewing direction.
				viewPos = coordSysTM.PointTransform(Point3(0.0f, 0.0f, fFar));
				lookAtPos = viewPos + viewDir;
				// In top view the up vector on the camera is the positive y-axis.
				if(viewExp->GetViewType() == VIEW_TOP)
					upVector.Set(0.0f, 1.0f, 0.0f);
				// In bottom view the up vector on the camera is the negative y-axis.
				if(viewExp->GetViewType() == VIEW_BOTTOM)
					upVector.Set(0.0f, -1.0f, 0.0f);
				break;
		}
		// When we are done with the viewport we should release it.
		_ip->ReleaseViewport(viewExp);

		// Set scene data.
		previewer.setSceneData(rootTransform.get());

		// set the view - OpenGL look at
		previewer.setViewMatrixAsLookAt(osg::Vec3( viewPos.x, viewPos.y, viewPos.z),
										 osg::Vec3(lookAtPos.x, lookAtPos.y, lookAtPos.z),
										 osg::Vec3(upVector.x, upVector.y, upVector.z) );
 		previewer.run();

		isExporting = FALSE;
		return TRUE;
	}
}
	isExporting = FALSE;
	return TRUE;
}
Beispiel #4
0
/**
*  @brief
*    Constructor
*/
PLSceneNode::PLSceneNode(PLSceneContainer *pContainer, IGameNode *pIGameNode, const String &sName, EType nType, const String &sClassName) :
	m_pContainer(pContainer),
	m_pIGameNode(pIGameNode),
	m_sName(sName),
	m_nType(nType),
	m_sClassName(sClassName),
	m_sFlags(""),
	m_vPos(0.0f, 0.0f, 0.0f),
	m_vRot(0.0f, 0.0f, 0.0f),
	m_vScale(1.0f, 1.0f, 1.0f),
	m_nIsRotationFlipped(-1)
{
	// Check some universal flags
	INode *pMaxNode = GetMaxNode();
	if (pMaxNode) { // If this is not a container...
		TSTR sString;

		// Check whether the default PixelLight class is changed
		if (pMaxNode->GetUserPropString(_T("Class"), sString)) {
			m_sClassName = sString;

			// Erase all '"'
			int i = m_sClassName.IndexOf("\"");
			while (i >= 0) {
				m_sClassName.Delete(i, 1);
				i = m_sClassName.IndexOf("\"");
			}
		}

		// Is this 3ds Max node frozen?
		if (pMaxNode->IsFrozen())
			AddFlag("Frozen");

		// Is this 3ds Max node invisible?
		if (pMaxNode->IsHidden() || !pMaxNode->Renderable())
			AddFlag("Invisible");

		// Is this 3ds Max node excluded from lighting?
		INodeGIProperties *pINodeGIProperties = static_cast<INodeGIProperties*>(pMaxNode->GetInterface(NODEGIPROPERTIES_INTERFACE));
		if (pINodeGIProperties && pINodeGIProperties->GIGetIsExcluded())
			AddFlag("NoLighting");

		{ // Get the world space bounding box of the scene node. Because this is not 'trival' we're using
		  // the sample code from "3dsMaxSDK.chm" (3ds Max SDK) -> "The Pipeline and the INode TM Methods"
		  // to get it working correctly.
			::Object *pMaxObject = pMaxNode->GetObjectRef();
			if (pMaxObject) {
				TimeValue t = 0;
				Matrix3 mat;	// The Object TM

				// Determine if the object is in world space or object space
				// so we can get the correct TM. We can check this by getting
				// the Object TM after the world space modifiers have been
				// applied. It the matrix returned is the identity matrix the
				// points of the object have been transformed into world space.
				if (pMaxNode->GetObjTMAfterWSM(t).IsIdentity()) {
					// It's in world space, so put it back into object
					// space. We can do this by computing the inverse
					// of the matrix returned before any world space
					// modifiers were applied.
					mat = Inverse(pMaxNode->GetObjTMBeforeWSM(t));
				} else { 
					// It's in object space, get the Object TM
					mat = pMaxNode->GetObjectTM(t);
				}

				// Get the bound box, and affect it by just the scaling portion
				pMaxObject->GetDeformBBox(t, m_cBoundingBox, &mat);
			}
		}

		// We really need to flip the coordinates to OpenGL style
		m_cBoundingBox.pmin = PLTools::Convert3dsMaxVectorToOpenGLVector(m_cBoundingBox.pmin);
		m_cBoundingBox.pmax = PLTools::Convert3dsMaxVectorToOpenGLVector(m_cBoundingBox.pmax);

		// Validate minimum/maximum - I already had situations with incorrect values causing problems!
		PLTools::ValidateMinimumMaximum(m_cBoundingBox);
	}

	// Get the position, rotation and scale
	GetPosRotScale(m_vPos, m_vRot, m_vScale);
}