bool SimpleCubeData::BuildBoundingBox()
{
   // Fusion uses Axis Aligned Bounding Boxes (AABBs) for its bounding volume heirarchy.  The bounding box should be provided
   // in the objects natural coordinate system.  The bounding box for the cube will be used for culling and other quick rejection 
   // tests.  It is recommeding you override this function always.  The default implementation will build the geometry for the cube 
   // and loop through all the vertices to brute force compute the bounding box.

   float32 hWidth  = 0.5f * Width;
   float32 hHeight = 0.5f * Height;
   float32 hDepth  = 0.5f * Depth;
	Vector3f bmin(-hWidth, -hHeight, -hDepth),bmax(hWidth, hHeight, hDepth);

   	Partio::ParticlesData* pdata;
	
	if (File)pdata=Partio::read(File);
	
	if (pdata){
		Partio::ParticleAttribute posAttr;
		uint32 pnum = pdata->numParticles();
		for (int i=0;i<pnum;i++)
                    {
                        const float* aapos=pdata->data<float>(posAttr,i);
                        bmin[0]=min(bmin[0],aapos[0]);bmin[1]=min(bmin[1],aapos[1]);bmin[2]=min(bmin[2],aapos[2]);
                        bmax[0]=max(bmax[0],aapos[0]);bmax[1]=max(bmax[1],aapos[1]);bmax[2]=max(bmax[2],aapos[2]);
                    }
		pdata->release();	
	}
	

   AABBSet = true;

   AABB.SetValue(bmin, bmax);

   return true;
}
Example #2
0
//
// test if a point lies in the linesegment. If the point isn't on the line
// the function returns a value that indicates on which side of the
// line the point is (in linedirection from first point to second point
//
// returns LEFT_SIDE, when point lies on the left side of the line
//         RIGHT_SIDE, when point lies on the right side of the line
//         ON_AREA, when point lies on the infinite line within a range
//     IN_AREA, when point lies in the area of the linesegment
//     the returnvalues are declared in (LINE.H)
PointStatus kbLine::PointInLine( kbNode *a_node, double& Distance, double Marge )
{
    Distance = 0;

    //Punt must exist
    assert( a_node );
    // link must exist to get beginnode and endnode via link
    assert( m_link );

    // get the nodes form the line via the link
    kbNode *bp, *ep;
    bp = m_link->GetBeginNode();
    ep = m_link->GetEndNode();

    // both node must exist
    assert( bp && ep );
    // node may not be the same
    assert( bp != ep );

    //quick test if point is begin or endpoint
    if ( a_node == bp || a_node == ep )
        return IN_AREA;

    int Result_of_BBox = false;
    PointStatus Result_of_Online;

    // Checking if point is in bounding-box with marge
    B_INT xmin = bmin( bp->GetX(), ep->GetX() );
    B_INT xmax = bmax( bp->GetX(), ep->GetX() );
    B_INT ymin = bmin( bp->GetY(), ep->GetY() );
    B_INT ymax = bmax( bp->GetY(), ep->GetY() );

    if (  a_node->GetX() >= ( xmin - Marge ) && a_node->GetX() <= ( xmax + Marge ) &&
            a_node->GetY() >= ( ymin - Marge ) && a_node->GetY() <= ( ymax + Marge ) )
        Result_of_BBox = true;

    // Checking if point is on the infinite line
    Result_of_Online = PointOnLine( a_node, Distance, Marge );

    // point in boundingbox of the line and is on the line then the point is IN_AREA
    if ( ( Result_of_BBox ) && ( Result_of_Online == ON_AREA ) )
        return IN_AREA;
    else
        return Result_of_Online;
}
 virtual void GetStats(PropertyMap& stats) const {
   MotionPlannerInterface::GetStats(stats);
   if(planner.dynamicDomain) {
     vector<Real> bmin(planner.bmin),bmax(planner.bmax);
     stats.setArray("gridMin",bmin);
     stats.setArray("gridMax",bmax);
   }
   stats.set("gridSize",planner.distances.numValues());
 }
//==============================================================================
SystemStats::CPUFlags::CPUFlags()
{
    // TODO
    hasMMX = false;
    hasSSE = false;
    hasSSE2 = false;
    has3DNow = false;

    numCpus = bmax (1, sysconf (_SC_NPROCESSORS_ONLN));
}
Example #5
0
DecodedBlob::DecodedBlob (void const* key, void const* value, int valueBytes)
{
    /*  Data format:

        Bytes

        0...3       LedgerIndex     32-bit big endian integer
        4...7       Unused?         An unused copy of the LedgerIndex
        8           char            One of NodeObjectType
        9...end                     The body of the object data
    */

    m_success = false;
    m_key = key;
    // VFALCO NOTE Ledger indexes should have started at 1
    m_ledgerIndex = LedgerIndex (-1);
    m_objectType = hotUNKNOWN;
    m_objectData = nullptr;
    m_dataBytes = bmax (0, valueBytes - 9);

    if (valueBytes > 4)
    {
        LedgerIndex const* index = static_cast <LedgerIndex const*> (value);
        m_ledgerIndex = ByteOrder::swapIfLittleEndian (*index);
    }

    // VFALCO NOTE What about bytes 4 through 7 inclusive?

    if (valueBytes > 8)
    {
        unsigned char const* byte = static_cast <unsigned char const*> (value);
        m_objectType = static_cast <NodeObjectType> (byte [8]);
    }

    if (valueBytes > 9)
    {
        m_objectData = static_cast <unsigned char const*> (value) + 9;

        switch (m_objectType)
        {
        case hotUNKNOWN:
        default:
            break;

        case hotLEDGER:
        case hotTRANSACTION:
        case hotACCOUNT_NODE:
        case hotTRANSACTION_NODE:
            m_success = true;
            break;
        }
    }
}
char* MemoryOutputStream::prepareToWrite (size_t numBytes)
{
    bassert ((ssize_t) numBytes >= 0);
    size_t storageNeeded = position + numBytes;

    if (storageNeeded >= data.getSize())
        data.ensureSize ((storageNeeded + bmin (storageNeeded / 2, (size_t) (1024 * 1024)) + 32) & ~31u);

    char* const writePointer = static_cast <char*> (data.getData()) + position;
    position += numBytes;
    size = bmax (size, position);
    return writePointer;
}
Example #7
0
// intersect a box
bool TXDualEdge::Touch(const CVector3f& minp, const CVector3f& maxp) const {
  int m = 4;

  CVector3f step;
  step.Sub(m_dp[1], m_dp[0]);
  step.ScaleInPlace(1/4);
  CVector3f A = m_dp[0];
  CVector3f B;
  B.Add(m_dp[0],step);

  for (int i = 0; i < m; i++) {
    CVector3f bmin(MIN(A.GetX(),B.GetX()),MIN(A.GetY(),B.GetY()),MIN(A.GetZ(),B.GetZ()));
	CVector3f bmax(MAX(A.GetX(),B.GetX()),MAX(A.GetY(),B.GetY()),MAX(A.GetZ(),B.GetZ()));

    if (bmin.GetX() <= maxp.GetX() && minp.GetX() <= bmax.GetX() &&
	bmin.GetY() <= maxp.GetY() && minp.GetY() <= bmax.GetY() &&
	bmin.GetZ() <= maxp.GetZ() && minp.GetZ() <= bmax.GetZ()) return true;
    A = B;
    B += step;
  }
  return false;
}
Example #8
0
int HullLibrary::calchullgen(btVector3 *verts,int verts_count, int vlimit)
{
	if(verts_count <4) return 0;
	if(vlimit==0) vlimit=1000000000;
	int j;
	btVector3 bmin(*verts),bmax(*verts);
	btAlignedObjectArray<int> isextreme;
	isextreme.reserve(verts_count);
	btAlignedObjectArray<int> allow;
	allow.reserve(verts_count);

	for(j=0;j<verts_count;j++) 
	{
		allow.push_back(1);
		isextreme.push_back(0);
		bmin.setMin (verts[j]);
		bmax.setMax (verts[j]);
	}
	btScalar epsilon = (bmax-bmin).length() * btScalar(0.001);
	btAssert (epsilon != 0.0);


	int4 p = FindSimplex(verts,verts_count,allow);
	if(p.x==-1) return 0; // simplex failed



	btVector3 center = (verts[p[0]]+verts[p[1]]+verts[p[2]]+verts[p[3]]) / btScalar(4.0);  // a valid interior point
	btHullTriangle *t0 = allocateTriangle(p[2],p[3],p[1]); t0->n=int3(2,3,1);
	btHullTriangle *t1 = allocateTriangle(p[3],p[2],p[0]); t1->n=int3(3,2,0);
	btHullTriangle *t2 = allocateTriangle(p[0],p[1],p[3]); t2->n=int3(0,1,3);
	btHullTriangle *t3 = allocateTriangle(p[1],p[0],p[2]); t3->n=int3(1,0,2);
	isextreme[p[0]]=isextreme[p[1]]=isextreme[p[2]]=isextreme[p[3]]=1;
	checkit(t0);checkit(t1);checkit(t2);checkit(t3);

	for(j=0;j<m_tris.size();j++)
	{
		btHullTriangle *t=m_tris[j];
		btAssert(t);
		btAssert(t->vmax<0);
		btVector3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]);
		t->vmax = maxdirsterid(verts,verts_count,n,allow);
		t->rise = dot(n,verts[t->vmax]-verts[(*t)[0]]);
	}
	btHullTriangle *te;
	vlimit-=4;
	while(vlimit >0 && ((te=extrudable(epsilon)) != 0))
	{
		int3 ti=*te;
		int v=te->vmax;
		btAssert(v != -1);
		btAssert(!isextreme[v]);  // wtf we've already done this vertex
		isextreme[v]=1;
		//if(v==p0 || v==p1 || v==p2 || v==p3) continue; // done these already
		j=m_tris.size();
		while(j--) {
			if(!m_tris[j]) continue;
			int3 t=*m_tris[j];
			if(above(verts,t,verts[v],btScalar(0.01)*epsilon)) 
			{
				extrude(m_tris[j],v);
			}
		}
		// now check for those degenerate cases where we have a flipped triangle or a really skinny triangle
		j=m_tris.size();
		while(j--)
		{
			if(!m_tris[j]) continue;
			if(!hasvert(*m_tris[j],v)) break;
			int3 nt=*m_tris[j];
			if(above(verts,nt,center,btScalar(0.01)*epsilon)  || cross(verts[nt[1]]-verts[nt[0]],verts[nt[2]]-verts[nt[1]]).length()< epsilon*epsilon*btScalar(0.1) )
			{
				btHullTriangle *nb = m_tris[m_tris[j]->n[0]];
				btAssert(nb);btAssert(!hasvert(*nb,v));btAssert(nb->id<j);
				extrude(nb,v);
				j=m_tris.size(); 
			}
		} 
		j=m_tris.size();
		while(j--)
		{
			btHullTriangle *t=m_tris[j];
			if(!t) continue;
			if(t->vmax>=0) break;
			btVector3 n=TriNormal(verts[(*t)[0]],verts[(*t)[1]],verts[(*t)[2]]);
			t->vmax = maxdirsterid(verts,verts_count,n,allow);
			if(isextreme[t->vmax]) 
			{
				t->vmax=-1; // already done that vertex - algorithm needs to be able to terminate.
			}
			else
			{
				t->rise = dot(n,verts[t->vmax]-verts[(*t)[0]]);
			}
		}
		vlimit --;
	}
	return 1;
}
Example #9
0
bool BufferedInputStream::setPosition (int64 newPosition)
{
    position = bmax ((int64) 0, newPosition);
    return true;
}
Example #10
0
void CAreaProxy::SerializeXML( XmlNodeRef &entityNode,bool bLoading )
{
	if (m_nFlags & FLAG_NOT_SERIALIZE)
		return;

	if (bLoading)
	{
		XmlNodeRef areaNode = entityNode->findChild( "Area" );
		if (!areaNode)
			return;

		int nId=0,nGroup=0,nPriority=0;
		float fProximity = 0;
		float fHeight = 0;
		
		areaNode->getAttr( "Id",nId );
		areaNode->getAttr( "Group",nGroup );
		areaNode->getAttr( "Proximity",fProximity );
		areaNode->getAttr( "Priority",nPriority );
		m_pArea->SetID(nId);
		m_pArea->SetGroup(nGroup);
		m_pArea->SetProximity(fProximity);
		m_pArea->SetPriority(nPriority);
		const char* token(0);

		XmlNodeRef pointsNode = areaNode->findChild( "Points" );
		if (pointsNode)
		{
			for (int i = 0; i < pointsNode->getChildCount(); i++)
			{
				XmlNodeRef pntNode = pointsNode->getChild(i);
				Vec3 pos;
				if (pntNode->getAttr( "Pos",pos ))
					m_localPoints.push_back(pos);

				// Get sound obstruction 
				bool bObstructSound = 0;
				pntNode->getAttr("ObstructSound", bObstructSound);
				m_abObstructSound.push_back(bObstructSound);
			}
			m_pArea->SetAreaType( ENTITY_AREA_TYPE_SHAPE );

			areaNode->getAttr( "Height",fHeight );
			m_pArea->SetHeight(fHeight);
			// Set points.
			OnMove();
		}
		else if (areaNode->getAttr("SphereRadius",m_fRadius))
		{
			// Sphere.
			areaNode->getAttr("SphereCenter",m_vCenter);
			m_pArea->SetSphere( m_pEntity->GetWorldTM().TransformPoint(m_vCenter),m_fRadius );
		}
		else if (areaNode->getAttr("VolumeRadius",m_fRadius))
		{
			areaNode->getAttr("Gravity",m_fGravity);
			areaNode->getAttr("DontDisableInvisible", m_bDontDisableInvisible);

			AABB box;
			box.Reset();

			// Bezier Volume.
			pointsNode = areaNode->findChild( "BezierPoints" );
			if (pointsNode)
			{
				for (int i = 0; i < pointsNode->getChildCount(); i++)
				{
					XmlNodeRef pntNode = pointsNode->getChild(i);
					Vec3 pt;
					if (pntNode->getAttr( "Pos",pt))
					{
						m_bezierPoints.push_back(pt);
						box.Add( pt );
					}
				}
			}
			m_pArea->SetAreaType( ENTITY_AREA_TYPE_GRAVITYVOLUME );
			if (!m_pEntity->GetRenderProxy())
			{
				IEntityRenderProxyPtr pRenderProxy = crycomponent_cast<IEntityRenderProxyPtr>(m_pEntity->CreateProxy( ENTITY_PROXY_RENDER ));
				m_pEntity->SetFlags(m_pEntity->GetFlags() | ENTITY_FLAG_SEND_RENDER_EVENT);

				if (box.min.x > box.max.x)
					box.min = box.max = Vec3(0,0,0);
				box.min-=Vec3(m_fRadius, m_fRadius, m_fRadius);
				box.max+=Vec3(m_fRadius, m_fRadius, m_fRadius);

				Matrix34 tm = m_pEntity->GetWorldTM_Fast();

				box.SetTransformedAABB( m_pEntity->GetWorldTM_Fast().GetInverted(),box );

				pRenderProxy->SetLocalBounds(box, true);
			}

			OnEnable(m_bIsEnable);
		}
		else if (areaNode->getAttr("AreaSolidFileName",&token))
		{
			CCryFile file;

			int nAliasLen = sizeof("%level%")-1;
			const char* areaSolidFileName;
			if (strncmp(token,"%level%",nAliasLen) == 0)
				areaSolidFileName = GetIEntitySystem()->GetSystem()->GetI3DEngine()->GetLevelFilePath(token+nAliasLen);
			else
				areaSolidFileName = token;

			if( file.Open(areaSolidFileName,"rb") )
			{
				int numberOfClosedPolygon = 0;
				int numberOfOpenPolygon = 0;

				m_pArea->BeginSettingSolid(m_pEntity->GetWorldTM());

				file.ReadType(&numberOfClosedPolygon);
				file.ReadType(&numberOfOpenPolygon);

				ReadPolygonsForAreaSolid( file, numberOfClosedPolygon, true );
				ReadPolygonsForAreaSolid( file, numberOfOpenPolygon, false );

				m_pArea->EndSettingSolid();
			}
		}
		else
		{
			// Box.
			Vec3 bmin(0,0,0),bmax(0,0,0);
			areaNode->getAttr("BoxMin",bmin);
			areaNode->getAttr("BoxMax",bmax);
			m_pArea->SetBox( bmin,bmax,m_pEntity->GetWorldTM() );

			// Get sound obstruction
			XmlNodeRef const pNodeSoundData = areaNode->findChild("SoundData");
			if (pNodeSoundData)
			{
				assert(m_abObstructSound.size() == 0);

				for (int i = 0; i < pNodeSoundData->getChildCount(); ++i)
				{
					XmlNodeRef const pNodeSide = pNodeSoundData->getChild(i);

					if (pNodeSide)
					{
						bool bObstructSound = false;
						pNodeSide->getAttr("ObstructSound", bObstructSound);
						m_abObstructSound.push_back(bObstructSound);
					}
				}
			}

			OnMove();
		}

		m_pArea->ClearEntities();
		XmlNodeRef entitiesNode = areaNode->findChild( "Entities" );
		// Export Entities.
		if (entitiesNode)
		{
			for (int i = 0; i < entitiesNode->getChildCount(); i++)
			{
				XmlNodeRef entNode = entitiesNode->getChild(i);
				EntityId entityId;
				EntityGUID entityGuid;
				if(gEnv->pEntitySystem->EntitiesUseGUIDs())
				{
					if (entNode->getAttr( "Guid",entityGuid ))
						m_pArea->AddEntity( entityGuid );
				}
				else
				{
					if (entNode->getAttr( "Id",entityId ))
						m_pArea->AddEntity( entityId );
				}
			}
		}
	}
	else
	{
		// Save points.
		XmlNodeRef areaNode = entityNode->newChild( "Area" );
		areaNode->setAttr( "Id",m_pArea->GetID() );
		areaNode->setAttr( "Group",m_pArea->GetGroup() );
		areaNode->setAttr( "Proximity",m_pArea->GetProximity() );
		areaNode->setAttr( "Priority", m_pArea->GetPriority() );
		EEntityAreaType type = m_pArea->GetAreaType();
		if (type == ENTITY_AREA_TYPE_SHAPE)
		{
			XmlNodeRef pointsNode = areaNode->newChild( "Points" );
			for (unsigned int i = 0; i < m_localPoints.size(); i++)
			{
				XmlNodeRef pntNode = pointsNode->newChild("Point");
				pntNode->setAttr( "Pos",m_localPoints[i] );
				pntNode->setAttr("ObstructSound", m_abObstructSound[i]);
			}
			areaNode->setAttr( "Height",m_pArea->GetHeight() );
		}
		else if (type == ENTITY_AREA_TYPE_SPHERE)
		{
			// Box.
			areaNode->setAttr("SphereCenter",m_vCenter);
			areaNode->setAttr("SphereRadius",m_fRadius);
		}
		else if (type == ENTITY_AREA_TYPE_BOX)
		{
			// Box.
			Vec3 bmin,bmax;
			m_pArea->GetBox(bmin,bmax);
			areaNode->setAttr("BoxMin",bmin);
			areaNode->setAttr("BoxMax",bmax);

			// Set sound obstruction
			XmlNodeRef const pNodeSoundData = areaNode->newChild("SoundData");
			if (pNodeSoundData)
			{
				assert(m_abObstructSound.size() == 6);
				size_t nIndex = 0;
				tSoundObstructionIterConst const ItEnd = m_abObstructSound.end();
				for (tSoundObstructionIterConst It = m_abObstructSound.begin(); It != ItEnd ; ++It)
				{
					bool const bObstructed = (bool)(*It);
					stack_string sTemp;
					sTemp.Format("Side%d", ++nIndex);

					XmlNodeRef const pNodeSide = pNodeSoundData->newChild(sTemp.c_str());
					pNodeSide->setAttr("ObstructSound", bObstructed);
				}
			}
		}
		else if (type == ENTITY_AREA_TYPE_GRAVITYVOLUME)
		{
			areaNode->setAttr("VolumeRadius",m_fRadius);
			areaNode->setAttr("Gravity",m_fGravity);
			areaNode->setAttr("DontDisableInvisible", m_bDontDisableInvisible);
			XmlNodeRef pointsNode = areaNode->newChild( "BezierPoints" );
			for (unsigned int i = 0; i < m_bezierPoints.size(); i++)
			{
				XmlNodeRef pntNode = pointsNode->newChild("Point");
				pntNode->setAttr( "Pos",m_bezierPoints[i] );
			}
		}

#ifdef SW_ENTITY_ID_USE_GUID
		const std::vector<EntityGUID>& entGUIDs=*m_pArea->GetEntitiesGuid();
		// Export Entities.
		if (!entGUIDs.empty())
		{
			XmlNodeRef nodes = areaNode->newChild( "Entities" );
			for (uint32 i = 0; i < entGUIDs.size(); i++)
			{
				EntityGUID guid = entGUIDs[i];
				XmlNodeRef entNode = nodes->newChild( "Entity" );
				entNode->setAttr( "Guid",guid );
				entNode->setAttr( "Id",gEnv->pEntitySystem->GenerateEntityIdFromGuid(guid) );
			}
		}
#else
		const std::vector<EntityId>& entIDs=*m_pArea->GetEntities();
		// Export Entities.
		if (!entIDs.empty())
		{
			XmlNodeRef nodes = areaNode->newChild( "Entities" );
			for (uint32 i = 0; i < entIDs.size(); i++)
			{
				int entityId = entIDs[i];
				XmlNodeRef entNode = nodes->newChild( "Entity" );
				entNode->setAttr( "Id",entityId );
			}
		}
#endif
	}
}
Example #11
0
int main( int argc, char** argv )
{
  if ( argc < 2 ) {
    std::cerr<<"Usage : "<<argv[0]<<" input.obj"<<std::endl;
    return -1;
  }
  std::cerr<<argv[1]<<std::endl;

  LG::PolygonMesh mesh;
  mesh.read(argv[1]);

  //// instantiate 4 vertex handles
  //LgMesh::PolygonMesh::Vertex v0,v1,v2,v3;

  //// add 4 vertices
  //v0 = mesh.add_vertex(LgMesh::Vec3(0,0,0));
  //v1 = mesh.add_vertex(LgMesh::Vec3(1,0,0));
  //v2 = mesh.add_vertex(LgMesh::Vec3(0,1,0));
  //v3 = mesh.add_vertex(LgMesh::Vec3(0,0,1));

  //// add 4 triangular faces
  //mesh.add_triangle(v0,v1,v3);
  //mesh.add_triangle(v1,v2,v3);
  //mesh.add_triangle(v2,v0,v3);
  //mesh.add_triangle(v0,v2,v1);

  mesh.update_face_normals();
  mesh.update_vertex_normals();

  std::cout << "vertices: " << mesh.n_vertices() << std::endl;
  std::cout << "edges: "    << mesh.n_edges()    << std::endl;
  std::cout << "faces: "    << mesh.n_faces()    << std::endl;

  //if ( !mesh.read(argv[1]) ) return -2;
  Eigen::Vector3d bmin(-1, -1, -1);
  Eigen::Vector3d bmax(1, 1, 1);
  //mesh.getBoundingBox(bmin, bmax);
  Camera camera(std::stod(std::string(argv[2])));
  camera.init( bmin, bmax );


  if ( glfwInit() == GL_FALSE ) return -1;
  Window win( 640, 480, "hello world" );
  if ( !win ) return -1;
  GLFWwindow* window = win.getWindow();

  initGL();
  while ( !glfwWindowShouldClose( window ) ) {

    glMatrixMode( GL_PROJECTION );
    glLoadIdentity();
    double fov, zNear, zFar;
    camera.getPerspective( fov, zNear, zFar );
    gluPerspective( fov, win.getAspectRatio(),  zNear, zFar );

    glMatrixMode( GL_MODELVIEW );
    glLoadIdentity();
    Eigen::Vector3d eye, center, up;
    camera.getLookAt( eye, center, up );
    gluLookAt( eye.x(), eye.y(), eye.z(), center.x(), center.y(), center.z(), up.x(), up.y(), up.z() );

    //オブジェクトの宙鮫
    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );

    LG::PolygonMesh::Face_iterator   fit;
    LG::PolygonMesh::Vertex_around_face_circulator vfc, vfc_end;
    LG::PolygonMesh::Face_attribute<LG::Vec3> f_normals = mesh.get_face_attribute<LG::Vec3>("f:normal");

    for (fit = mesh.faces_begin(); fit != mesh.faces_end(); ++fit)
    {
      glBegin(GL_TRIANGLES);
      LG::Vec3 n = f_normals[*fit];
      glNormal3d(n.x(), n.y(), n.z());

      vfc = mesh.vertices(*fit);
      vfc_end = vfc;

      do 
      {
        LG::Vec3 vp = mesh.position((*vfc));
        glVertex3d ( vp.x(), vp.y(), vp.z());
      } while (++vfc != vfc_end);

      glEnd();

    }
    glfwSwapBuffers( window );


    //マウスイベントの函誼
    glfwWaitEvents();
    double oldx, oldy, newx, newy;
    win.getMousePosition( oldx, oldy, newx, newy );
    if ( glfwGetMouseButton( window, GLFW_MOUSE_BUTTON_1 ) != GLFW_RELEASE ) {
      camera.rotate( oldx, oldy, newx, newy );
    }
  }
  return 0;
}