VDPMLoader::~VDPMLoader(){
    this->qFilename_.clear();
    this->mesh_loaded = false;
    vsplit_loaded.clear();
    vfront_.clear();
    vhierarchy_.clear();
    index2handle_map.clear();
    
    //mesh_.clear();
    
    VDPMMesh::FaceIter fIt(mesh_.faces_begin()), fEnd(mesh_.faces_end());
    
    for(; fIt != fEnd; ++fIt){
        mesh_.delete_face(fIt.handle());
    }
    VDPMMesh::VertexIter vIt(mesh_.vertices_begin()), vEnd(mesh_.vertices_end());
    for(; vIt != vEnd; ++vIt){
        mesh_.delete_vertex(vIt.handle());
    }
    mesh_.garbage_collection();
    if(base_info_data != NULL){
        delete  [] base_info_data;
        base_info_data = NULL;
    }
    base_info_data_size = 0;
    

}
Esempio n. 2
0
void transform(const TMeshImageP &meshImage, const TAffine &aff) {
  const std::vector<TTextureMeshP> &meshes = meshImage->meshes();

  int m, mCount = meshes.size();
  for (m = 0; m != mCount; ++m) {
    TTextureMesh &mesh = *meshes[m];

    tcg::list<TTextureMesh::vertex_type> &vertices = mesh.vertices();

    tcg::list<TTextureMesh::vertex_type>::iterator vt, vEnd(vertices.end());
    for (vt = vertices.begin(); vt != vEnd; ++vt) vt->P() = aff * vt->P();
  }
}
Esempio n. 3
0
/**
 * @return The angle from between two vectors using the current vector as the center
 * return 0, if the angle is not well defined
 */
double RS_Vector::angleBetween(const RS_Vector& v1, const RS_Vector& v2) const {
    if (!valid || !v1.valid || !v2.valid) {
        return 0.0;
    }
    else {
        RS_Vector vStart(v1- (*this));
        RS_Vector vEnd(v2- (*this));
        //        if( vStart.magnitude() < RS_TOLERANCE
        //                || vEnd.magnitude() < RS_TOLERANCE) return 0.0;
        return RS_Math::correctAngle( atan2( vStart.x*vEnd.y-vStart.y*vEnd.x, vStart.x*vEnd.x+vStart.y*vEnd.y));

        //         std::cout<<"old algorithm:: "<<RS_Math::correctAngle(vEnd.angle() - vStart.angle())<<std::endl;
//        return RS_Math::correctAngle(vEnd.angle() - vStart.angle());
    }
}
Esempio n. 4
0
/**
  * this should handle modifyOffset
  *@ coord, indicate direction of offset
  *@ distance of offset
  *
  *@Author, Dongxu Li
  */
bool RS_Polyline::offset(const RS_Vector& coord, const double& distance){
    double dist;
    //find the nearest one
    int length=count();
		std::vector<RS_Vector> intersections(length);
    if(length>1){//sort the polyline entity start/end point order
        int i(0);
        double d0,d1;
        RS_Entity* en0(entityAt(0));
        RS_Entity* en1(entityAt(1));

        RS_Vector vStart(en0->getStartpoint());
        RS_Vector vEnd(en0->getEndpoint());
        en1->getNearestEndpoint(vStart,&d0);
        en1->getNearestEndpoint(vEnd,&d1);
        if(d0<d1) en0->revertDirection();
        for(i=1;i<length;en0=en1){
                //linked to head-tail chain
            en1=entityAt(i);
            vStart=en1->getStartpoint();
            vEnd=en1->getEndpoint();
            en0->getNearestEndpoint(vStart,&d0);
            en0->getNearestEndpoint(vEnd,&d1);
            if(d0>d1) en1->revertDirection();
            intersections[i-1]=(en0->getEndpoint()+en1->getStartpoint())*0.5;
            i++;
        }

    }
    RS_Entity* en(getNearestEntity(coord, &dist, RS2::ResolveNone));
    if(en==NULL) return false;
    int indexNearest=findEntity(en);
    //        RS_Vector vp(en->getNearestPointOnEntity(coord,false));
    //        RS_Vector direction(en->getTangentDirection(vp));
    //        RS_Vector vp1(-direction.y,direction.x);//normal direction
    //        double a2(vp1.squared());
    //        if(a2<RS_TOLERANCE2) return false;
    //        vp1 *= distance/sqrt(a2);
    //        move(vp1);
    //        return true;

    RS_Polyline* pnew= static_cast<RS_Polyline*>(clone());
    int i;
    i=indexNearest;
    int previousIndex(i);
    pnew->entityAt(i)->offset(coord,distance);
    RS_Vector vp;
    //offset all
    //fixme, this is too ugly
    for(i=indexNearest-1;i>=0;i--){
        RS_VectorSolutions sol0=RS_Information::getIntersection(pnew->entityAt(previousIndex),entityAt(i),true);
//        RS_VectorSolutions sol1;
        double dmax(RS_TOLERANCE15);
        RS_Vector trimP(false);
		for(const RS_Vector& vp: sol0){

			double d0( (vp - pnew->entityAt(previousIndex)->getStartpoint()).squared());//potential bug, need to trim better
            if(d0>dmax) {
                dmax=d0;
				trimP=vp;
            }
        }
        if(trimP.valid){
            static_cast<RS_AtomicEntity*>(pnew->entityAt(previousIndex))->trimStartpoint(trimP);
            static_cast<RS_AtomicEntity*>(pnew->entityAt(i))->trimEndpoint(trimP);
            vp=pnew->entityAt(previousIndex)->getMiddlePoint();
        }else{
            vp=pnew->entityAt(previousIndex)->getStartpoint();
            vp.rotate(entityAt(previousIndex)->getStartpoint(),entityAt(i)->getDirection2()-entityAt(previousIndex)->getDirection1()+M_PI);
        }
        pnew->entityAt(i)->offset(vp,distance);
        previousIndex=i;
    }

    previousIndex=indexNearest;
    for(i=indexNearest+1;i<length;i++){
        RS_VectorSolutions sol0=RS_Information::getIntersection(pnew->entityAt(previousIndex),entityAt(i),true);
//        RS_VectorSolutions sol1;
        double dmax(RS_TOLERANCE15);
        RS_Vector trimP(false);
		for(const RS_Vector& vp: sol0){
			double d0( (vp - pnew->entityAt(previousIndex)->getEndpoint()).squared());//potential bug, need to trim better
            if(d0>dmax) {
                dmax=d0;
				trimP=vp;
            }
        }
        if(trimP.valid){
            static_cast<RS_AtomicEntity*>(pnew->entityAt(previousIndex))->trimEndpoint(trimP);
            static_cast<RS_AtomicEntity*>(pnew->entityAt(i))->trimStartpoint(trimP);
            vp=pnew->entityAt(previousIndex)->getMiddlePoint();
        }else{
            vp=pnew->entityAt(previousIndex)->getEndpoint();
            vp.rotate(entityAt(previousIndex)->getEndpoint(),entityAt(i)->getDirection1()-entityAt(previousIndex)->getDirection2()+M_PI);
        }
        pnew->entityAt(i)->offset(vp,distance);
        previousIndex=i;
    }
    //trim
    //connect and trim        RS_Modification m(*container, graphicView);
    for(i=0;i<length-1;i++){
        RS_VectorSolutions sol0=RS_Information::getIntersection(pnew->entityAt(i),pnew->entityAt(i+1),true);
        if(sol0.getNumber()==0) {
            sol0=RS_Information::getIntersection(pnew->entityAt(i),pnew->entityAt(i+1));
//            RS_Vector vp0(pnew->entityAt(i)->getEndpoint());
//            RS_Vector vp1(pnew->entityAt(i+1)->getStartpoint());
//            double a0(intersections.at(i).angleTo(vp0));
//            double a1(intersections.at(i).angleTo(vp1));
            RS_VectorSolutions sol1;
			for(const RS_Vector& vp: sol0){
				if(RS_Math::isAngleBetween(intersections.at(i).angleTo(vp),
                                           pnew->entityAt(i)->getDirection2(),
                                           pnew->entityAt(i+1)->getDirection1(),
                                           false)==false){
					sol1.push_back(vp);
                }
            }
            if(sol1.getNumber()==0) continue;
            RS_Vector trimP(sol1.getClosest(intersections.at(i)));
            static_cast<RS_AtomicEntity*>(pnew->entityAt(i))->trimEndpoint(trimP);
            static_cast<RS_AtomicEntity*>(pnew->entityAt(i+1))->trimStartpoint(trimP);
        }else{
            RS_Vector trimP(sol0.getClosest(pnew->entityAt(i)->getStartpoint()));
            static_cast<RS_AtomicEntity*>(pnew->entityAt(i))->trimEndpoint(trimP);
            static_cast<RS_AtomicEntity*>(pnew->entityAt(i+1))->trimStartpoint(trimP);
        }

    }

    *this = *pnew;
    return true;


}
Esempio n. 5
0
//-----------------------------------------------------------------------------
// Purpose: 
// Input  : time - 
//			type - 
// Output : float
//-----------------------------------------------------------------------------
float CSentence::GetIntensity( float time, float endtime )
{
	float zeroValue = 0.5f;
	
	int c = GetNumSamples();
	
	if ( c <= 0 )
	{
		return zeroValue;
	}
	
	int i;
	for ( i = -1 ; i < c; i++ )
	{
		CEmphasisSample *s = GetBoundedSample( i, endtime );
		CEmphasisSample *n = GetBoundedSample( i + 1, endtime );
		if ( !s || !n )
			continue;

		if ( time >= s->time && time <= n->time )
		{
			break;
		}
	}

	int prev = i - 1;
	int start = i;
	int end = i + 1;
	int next = i + 2;

	prev = max( -1, prev );
	start = max( -1, start );
	end = min( end, GetNumSamples() );
	next = min( next, GetNumSamples() );

	CEmphasisSample *esPre = GetBoundedSample( prev, endtime );
	CEmphasisSample *esStart = GetBoundedSample( start, endtime );
	CEmphasisSample *esEnd = GetBoundedSample( end, endtime );
	CEmphasisSample *esNext = GetBoundedSample( next, endtime );

	float dt = esEnd->time - esStart->time;
	dt = clamp( dt, 0.01f, 1.0f );

	Vector vPre( esPre->time, esPre->value, 0 );
	Vector vStart( esStart->time, esStart->value, 0 );
	Vector vEnd( esEnd->time, esEnd->value, 0 );
	Vector vNext( esNext->time, esNext->value, 0 );

	float f2 = ( time - esStart->time ) / ( dt );
	f2 = clamp( f2, 0.0f, 1.0f );

	Vector vOut;
	Catmull_Rom_Spline( 
		vPre,
		vStart,
		vEnd,
		vNext,
		f2, 
		vOut );

	float retval = clamp( vOut.y, 0.0f, 1.0f );
	return retval;
}
Esempio n. 6
0
//determines if the specified segment intersects a polygon. It fills out
//passed in datastructure appropriately.
bool CLightingBSP::IntersectSegment(const PVector& vSegStart, const PVector& vSegEnd, 
									CLightBSPStack* pStack, CIntersectInfo* pInfo) const
{
	ASSERT(pStack);

	uint32 nStackOff = 0;

	//the working endpoints
	PVector vStart(vSegStart);
	PVector vEnd(vSegEnd);

	//the polygon hit
	CLightBSPPoly* pHitPoly;

	//the working node
	CLightBSPNode* pNode = m_pHead;

	while(1)
	{
		//classify the points
		PReal fStartDot = vStart.Dot(pNode->m_vPlaneNorm) - pNode->m_fPlaneDist;
		PReal fEndDot	= vEnd.Dot(pNode->m_vPlaneNorm) - pNode->m_fPlaneDist;

		//check for the same side
		if((fStartDot >= 0) && (fEndDot >= 0))
		{
			//we are in the front
			pNode = pNode->m_pFront;
		}
		else if((fStartDot < 0) && (fEndDot < 0))
		{
			//we are in the back
			pNode = pNode->m_pBack;
		}
		else
		{
			//save the node that we want to test first
			pStack[nStackOff].m_pTest	= pNode;
			pStack[nStackOff].m_vEnd	= vEnd;

			//we have intersected
			if(fStartDot < 0)
			{
				//setup our stack information
				pStack[nStackOff].m_pNode	= pNode->m_pFront;

				//we do the back first
				pNode = pNode->m_pBack;
			}
			else
			{
				//setup our stack information
				pStack[nStackOff].m_pNode	= pNode->m_pBack;

				//we do the front first
				pNode = pNode->m_pFront;
			}

			//calculate the new working endpoint
			vEnd = vStart + (vEnd - vStart) * -fStartDot / (fEndDot - fStartDot);

			//next stack item
			nStackOff++;
		}

		//if we hit a null node, we need to bubble out of the stack, or bail
		while(pNode == NULL)
		{
			//if the stack is empty, no intersection occurred
			if(nStackOff == 0)
				return false;

			//pop the stack
			nStackOff--;

			//the stack is not empty, we need to test against the specified node,
			//and then check behind it if no hit occurred
			if(pHitPoly = CheckHitNode(pStack[nStackOff].m_pTest, vEnd))
			{
				if(pInfo)
				{
					pInfo->m_vNormal		= pStack[nStackOff].m_pTest->m_vPlaneNorm;
					pInfo->m_vIntersectPt	= vEnd;
					pInfo->m_nFlags			= pHitPoly->m_nFlags;
				}
				return true;
			}

			//no intersection, so we now need to process the back half
			vStart = vEnd;
			vEnd = pStack[nStackOff].m_vEnd;
			pNode = pStack[nStackOff].m_pNode;
		}

	} //infinite loop. Exits when stack is popped off completely, or when poly is hit
}
Esempio n. 7
0
bool ExportMediaDialog::MessageReceived(EMListenerRepository* p_opSender, uint32 p_vMessage)
{
	switch(p_vMessage)
	{
/*	case EM_DRAW:
		if(p_opSender == m_opMainView)
		{
			eo << "EM_DRAW: m_oBackgroundView" << ef;
			m_opMainView -> SetHighColor(EMColor(0, 255, 0, 255));
			m_opMainView -> FillRect(m_opMainView -> Bounds());
		}
		else
			eo << "EM_DRAW (unknown)" << ef;
		return true;
*/	case EM_BUTTON_SETTINGS:
		EMCommandRepository::Instance() -> ExecuteCommand(COMMAND_DISPLAY_EXPORT_MEDIA_SETTINGS_DIALOG, m_opDialogWindow, reinterpret_cast<void*>(m_opExportTypeComboBox -> GetSelectionIndex()), this);
		m_opExportTypeComboBox -> Notify(EXPORT_TYPE_COMBO_BOX_CHANGED);
		return true;
	case EM_BUTTON_BROWSE:
		eo << "Browse button pressed" << ef;
		if(m_opBrowseWindow == NULL)
			m_opBrowseWindow = EMFactory::Instance() -> CreateBrowseWindow(m_opMainView -> GetNativeView(), "Browse");
		if(m_opBrowseWindow -> DisplayDialog())
			m_opExportToTextControl -> SetText(m_opBrowseWindow -> GetPath() -> c_str());

		return true;
/*	case EM_BUTTON_SAVE_TEMPLATE:
		eo << "Save Template button pressed" << ef;
		return true;
	case EM_BUTTON_DELETE_TEMPLATE:
		eo << "Delete Template button pressed" << ef;
		return true;
*/	case EM_RENDERING_COULD_NOT_START:
		if(m_vExporting)
			StopExporting(false);
		return true;
	case EM_RENDERING_HAS_FINNISHED:
		if(m_vExporting == false)
			return true;
	case EM_GUI_COMPONENT_ENTER_PRESSED:
	case EM_BUTTON_EXPORT:
		{
		eo << "Export button pressed" << ef;
			if(m_vExporting == false)
			{
				if(InvalidCharExist(m_opExportToTextControl -> Text(), m_opFilenameTextControl -> Text()))
				{
					eo << "Invalid Character found!!" << ef;
					return true;
				}

				string oDirectoryTemp = m_opExportToTextControl -> Text();
				if(oDirectoryTemp.length() != oDirectoryTemp.find_last_of("\\") + 1)
				{
					oDirectoryTemp.append("\\");
					m_opExportToTextControl -> SetText(oDirectoryTemp.c_str());
				}


				int vResult = CreateDir(const_cast<char*>(m_opExportToTextControl -> Text()), const_cast<char*>(m_opFilenameTextControl -> Text()));
				switch(vResult)
				{
				case RESULT_OK:
					m_vExporting = true;
					m_vExportTypeOld = m_opExportTypeComboBox -> GetSelectionIndex();
					m_oExportToOld = m_opExportToTextControl -> Text();
				//	m_oFilenameOld = m_
					Export();
					return true;
				case RESULT_NOT_OK:
				case RESULT_NO_BUTTON:
					eo << "Go back to dialog" << ef;
					return true;
				case RESULT_CANCEL_BUTTON:
					eo << "Close dialog and do nothing" << ef;
					break;
				}
			}
			else
			{
				StopExporting();
				return true;
			}
			HideDialog();
			return true;
		}
	case EM_GUI_COMPONENT_ESC_PRESSED:
	case EM_BUTTON_CANCEL:
		eo << "Cancel button pressed" << ef;
		if(m_vExporting)
			StopExporting();
		HideDialog();
		return true;
	case EM_TEXT_CONTROL_CHANGE:
		eo << "EM_TEXT_CONTROL_FILENAME_CHANGE" << ef;
		if(strlen(m_opFilenameTextControl -> Text()) == 0 || strlen(m_opExportToTextControl -> Text()) == 0)
			m_opExportButton -> Enable(false);
		else
			m_opExportButton -> Enable(true);
		if(p_opSender == m_opExportToTextControl)
		{
			if(m_vFilenameChanged)
			{
				m_vExportToChanged = false;
				m_vFilenameChanged = false;
			}
			else
				m_vExportToChanged = true;
		}
		if(p_opSender == m_opFilenameTextControl)
		{
			m_vFilenameChanged = true;
			AddToExportToTextControl();
		}
		return true;
	case EM_GUI_COMPONENT_GOT_FOCUS:
		eo << "EM_TEXT_CONTROL_GOT_FOCUS" << ef;
		if(p_opSender == m_opFilenameTextControl)
		{
			eo << "Filename got Focus" << ef;
			string oFilename(m_opFilenameTextControl -> Text());
			m_opFilenameTextControl -> SetSelection(0, oFilename.find_last_of('.'));
		}
		if(p_opSender == m_opDialogWindow)
			m_opExportButton -> SetFocus();
		m_opDialogWindow -> SetCurrentFocus();
		return true;
	case EM_GUI_COMPONENT_TAB_PRESSED:
		eo << "EM_GUI_COMPONENT_TAB_PRESSED" << ef;
		m_opDialogWindow -> NextTab();
		return true;
	case EM_GUI_COMPONENT_SHIFT_TAB_PRESSED:
		m_opDialogWindow -> PreviousTab();
		return true;
	case EM_TEXT_CONTROL_END_PRESSED:
		if(p_opSender == m_opFilenameTextControl)
		{
			eo << "EM_TEXT_CONTROL_END_ARROW_PRESSED" << ef;
			uint32 vModifiers = EMKeyboard::Instance() -> GetModifiers();
			if((vModifiers & EM_SHIFT_KEY) == EM_SHIFT_KEY)
			{
				int32 vStart(0);
				int32 vEnd(0);
				m_opFilenameTextControl -> GetSelection(vStart, vEnd);
				m_opFilenameTextControl -> SetSelection(vStart, strlen(m_opFilenameTextControl -> Text()) - m_oFileExtension.length());
			}
			else
				m_opFilenameTextControl -> SetSelection(strlen(m_opFilenameTextControl -> Text()) - m_oFileExtension.length(), strlen(m_opFilenameTextControl -> Text()) - m_oFileExtension.length());
			return true;
		}
		return false;
	case EM_TEXT_CONTROL_DELETE_PRESSED:
		if(p_opSender == m_opFilenameTextControl)
		{
			eo << "EM_TEXT_CONTROL_DELETE_PRESSED" << ef;
			int32 vStart(0);
			int32 vEnd(0);
			m_opFilenameTextControl -> GetSelection(vStart, vEnd);
			if(vStart == vEnd && vEnd >= strlen(m_opFilenameTextControl -> Text()) - m_oFileExtension.length())
				return true;
		}
		return false;
	case EM_TEXT_CONTROL_DOWN_ARROW_PRESSED:
	case EM_TEXT_CONTROL_RIGHT_ARROW_PRESSED:
		if(p_opSender == m_opFilenameTextControl)
		{
			eo << "EM_TEXT_CONTROL_DOWN/RIGHT_ARROW_PRESSED" << ef;
			int32 vStart(0);
			int32 vEnd(0);
			m_opFilenameTextControl -> GetSelection(vStart, vEnd);
			if(vEnd >= strlen(m_opFilenameTextControl -> Text()) - m_oFileExtension.length())
				return true;
		}
		return false;
	case EM_TEXT_CONTROL_LEFT_MOUSE_BUTTON_DOWN:
		if(p_opSender == m_opFilenameTextControl)
		{
			int32 vStart(0);
			int32 vEnd(0);
			m_opFilenameTextControl -> GetSelection(vStart, vEnd);
			if(vEnd >= strlen(m_opFilenameTextControl -> Text()) - m_oFileExtension.length() && vStart >= strlen(m_opFilenameTextControl -> Text()) - m_oFileExtension.length())
			{
				m_opFilenameTextControl -> SetSelection(strlen(m_opFilenameTextControl -> Text()) - m_oFileExtension.length(), strlen(m_opFilenameTextControl -> Text()) - m_oFileExtension.length());
				//return true;
			}
			else if(vEnd >= strlen(m_opFilenameTextControl -> Text()) - m_oFileExtension.length() && vStart < strlen(m_opFilenameTextControl -> Text()) - m_oFileExtension.length())
			{
				m_opFilenameTextControl -> SetSelection(vStart, strlen(m_opFilenameTextControl -> Text()) - m_oFileExtension.length());
				//return true;
			}

		}
		return false;
	case EM_TEXT_CONTROL_MENU_SELECTED:
		eo << "EM_TEXT_CONTROL_MENU_SELECTED" << ef;
		if(p_opSender == m_opFilenameTextControl)
		{
			m_vSelectedFromMenu = true;
			return true;
		}
		return false;
	case EM_TEXT_CONTROL_SET_SELECTION:
		eo << "EM_TEXT_CONTROL_SET_SELECTION" << ef;
		if(p_opSender == m_opFilenameTextControl)
		{
			if(m_vSelectedFromMenu)
			{
				m_vSelectedFromMenu = false;
				m_opFilenameTextControl -> SetSelection(0, strlen(m_opFilenameTextControl -> Text()) - m_oFileExtension.length());
				return true;
			}
		}
		return false;
	case EXPORT_TYPE_COMBO_BOX_CHANGED:
		{
			eo << "EXPORT_TYPE_COMBO_BOX_CHANGED" << ef;
			switch(m_opExportTypeComboBox -> GetSelectionIndex())
			{
			case 0:
				m_vRenderAudio = true;
				m_vRenderVideo = false;
				m_oFileExtension = ".wav";
				break;
			case 1:
				m_vRenderAudio = true;
				m_vRenderVideo = true;
				//m_oFileExtension = ".avi";
				m_oFileExtension = ExportMediaSettingsDialog::m_vFileExtension;
				break;
			case 2:
				m_vRenderAudio = false;
				m_vRenderVideo = true;
				//m_oFileExtension = ".avi";
				m_oFileExtension = ExportMediaSettingsDialog::m_vFileExtension;
				break;
			}
			string oFilename;
			oFilename.append(m_oDefaultFilename);
			oFilename.append(m_oFileExtension);
			m_opFilenameTextControl -> SetText(oFilename.c_str());
			return true;
		}
	case EM_CLOSE_WINDOW:
		eo << "EM_CLOSE_WINDOW" << ef;
		if(m_vExporting)
		{
			StopExporting();
			return true;
		}
		HideDialog();
		return true;
	}
	return false;
}
void VDPMLoader::openVDPM_ServerRendering(const char *_filename)
{
    unsigned int                    i;
    unsigned int                    value;
    unsigned int                    fvi[3];
    char                            fileformat[16];
    Vec3f                           p, normal;
    float                           radius, sin_square, mue_square, sigma_square;
    VHierarchyNodeHandleContainer   roots;
    VertexHandle                    vertex_handle;
    VHierarchyNodeIndex             node_index;
    VHierarchyNodeIndex             lchild_node_index, rchild_node_index;
    VHierarchyNodeIndex             fund_lcut_index, fund_rcut_index;
    VHierarchyNodeHandle            node_handle;
    VHierarchyNodeHandle            lchild_node_handle, rchild_node_handle;
    
    
    
    std::ifstream ifs(_filename, std::ios::binary);
    
    if (!ifs)
    {
        std::cerr << "read error\n";
        exit(1);
    }
    
    //
    bool swap = Endian::local() != Endian::LSB;
    
    // read header
    ifs.read(fileformat, 10); fileformat[10] = '\0';
    if (std::string(fileformat) != std::string("VDProgMesh"))
    {
        std::cerr << "Wrong file format.\n";
        ifs.close();
        exit(1);
    }
    
    IO::restore(ifs, n_base_vertices_, swap);
    IO::restore(ifs, n_base_faces_, swap);
    IO::restore(ifs, n_details_, swap);
    
    mesh_.clear();
    vfront_.clear();
    vhierarchy_.clear();
    
    vhierarchy_.set_num_roots(n_base_vertices_);
    
    
    // load base mesh
    for (i=0; i<n_base_vertices_; ++i)
    {
        IO::restore(ifs, p, swap);
        IO::restore(ifs, radius, swap);
        IO::restore(ifs, normal, swap);
        IO::restore(ifs, sin_square, swap);
        IO::restore(ifs, mue_square, swap);
        IO::restore(ifs, sigma_square, swap);
        
        vertex_handle = mesh_.add_vertex(p);
        node_index    = vhierarchy_.generate_node_index(i, 1);
        node_handle   = vhierarchy_.add_node();
        
        VHierarchyNode &node = vhierarchy_.node(node_handle);
        
        node.set_index(node_index);
        node.set_vertex_handle(vertex_handle);
        mesh_.data(vertex_handle).set_vhierarchy_node_handle(node_handle);
        
        node.set_radius(radius);
        node.set_normal(normal);
        node.set_sin_square(sin_square);
        node.set_mue_square(mue_square);
        node.set_sigma_square(sigma_square);
        mesh_.set_normal(vertex_handle, normal);
        
        index2handle_map[node_index] = node_handle;
        roots.push_back(node_handle);
    }
    vfront_.init(roots, n_details_);
    
    for (i=0; i<n_base_faces_; ++i)
    {
        IO::restore(ifs, fvi[0], swap);
        IO::restore(ifs, fvi[1], swap);
        IO::restore(ifs, fvi[2], swap);
        
        mesh_.add_face(mesh_.vertex_handle(fvi[0]),
                       mesh_.vertex_handle(fvi[1]),
                       mesh_.vertex_handle(fvi[2]));
    }
    
    vsplit_loaded.clear();
    
    // load details
    for (i=0; i<n_details_; ++i)
    {
        Vsplit avs;
        // position of v0
        IO::restore(ifs, p, swap);
        
        avs.v0 = p;
        
        // vsplit info.
        IO::restore(ifs, value, swap);
        node_index = VHierarchyNodeIndex(value);
        
        avs.node_index = value;
        
        IO::restore(ifs, value, swap);
        fund_lcut_index = VHierarchyNodeIndex(value);
        
        avs.fund_lcut_index = value;
        
        IO::restore(ifs, value, swap);
        fund_rcut_index = VHierarchyNodeIndex(value);
        
        avs.fund_rcut_index = value;
        
        node_handle = index2handle_map[node_index];
        vhierarchy_.make_children(node_handle);
        
        VHierarchyNode &node   = vhierarchy_.node(node_handle);
        VHierarchyNode &lchild = vhierarchy_.node(node.lchild_handle());
        VHierarchyNode &rchild = vhierarchy_.node(node.rchild_handle());
        
        node.set_fund_lcut(fund_lcut_index);
        node.set_fund_rcut(fund_rcut_index);
        
        vertex_handle = mesh_.add_vertex(p);
        lchild.set_vertex_handle(vertex_handle);
        rchild.set_vertex_handle(node.vertex_handle());
        
        index2handle_map[lchild.node_index()] = node.lchild_handle();
        index2handle_map[rchild.node_index()] = node.rchild_handle();
        
        // view-dependent parameters
        IO::restore(ifs, radius, swap);
        IO::restore(ifs, normal, swap);
        IO::restore(ifs, sin_square, swap);
        IO::restore(ifs, mue_square, swap);
        IO::restore(ifs, sigma_square, swap);
        lchild.set_radius(radius);
        lchild.set_normal(normal);
        lchild.set_sin_square(sin_square);
        lchild.set_mue_square(mue_square);
        lchild.set_sigma_square(sigma_square);
        
        avs.l_radius = radius;
        avs.l_normal = normal;
        avs.l_mue_square = mue_square;
        avs.l_sigma_square = sigma_square;
        avs.l_sin_square = sin_square;
        
        IO::restore(ifs, radius, swap);
        IO::restore(ifs, normal, swap);
        IO::restore(ifs, sin_square, swap);
        IO::restore(ifs, mue_square, swap);
        IO::restore(ifs, sigma_square, swap);
        rchild.set_radius(radius);
        rchild.set_normal(normal);
        rchild.set_sin_square(sin_square);
        rchild.set_mue_square(mue_square);
        rchild.set_sigma_square(sigma_square);
        
        avs.r_radius = radius;
        avs.r_normal = normal;
        avs.r_mue_square = mue_square;
        avs.r_sigma_square = sigma_square;
        avs.r_sin_square = sin_square;
        
        vsplit_loaded.push_back(avs);
        
    }
    
    ifs.close();
    
    //refine 100 vsplits
    int cc = 0;
    for ( vfront_.begin(); !vfront_.end() && cc < 100; ++cc)
    {
        VHierarchyNodeHandle
        node_handle   = vfront_.node_handle();
        
        if (vhierarchy_.is_leaf_node(node_handle) != true)
        {
            force_vsplit(node_handle, vsplits_to_send);
        }
        vfront_.next();
        std::cout << "vfront_ size " << vfront_.size() <<std::endl;
    }
    
    //**********//

    
    // update face and vertex normals
    mesh_.update_face_normals();
    
    // bounding box
    VDPMMesh::ConstVertexIter
    vIt(mesh_.vertices_begin()),
    vEnd(mesh_.vertices_end());
    
    VDPMMesh::Point bbMin, bbMax;
    
    bbMin = bbMax = mesh_.point(vIt);
    for (; vIt!=vEnd; ++vIt)
    {
        bbMin.minimize(mesh_.point(vIt));
        bbMax.maximize(mesh_.point(vIt));
    }
    
    // set center and radius
    VDPMMesh::Point center = 0.5f * (bbMin + bbMax);
    set_scene_pos(0.5f*(bbMin + bbMax), 0.5*(bbMin - bbMax).norm());
    
    
    
    // info
    std::cerr << mesh_.n_vertices() << " vertices, "
    << mesh_.n_edges()    << " edge, "
    << mesh_.n_faces()    << " faces, "
    << n_details_ << " detail vertices\n";
    
    mesh_loaded = true;
}