// reads in bounds block from anim file
void MD5Model::readBoundsEl(std::ifstream &fin, Anim &anim) {
	TOKEN t = getNextToken(fin);

	// expect an opening brace { to begin block
	if (t != TOKEN_LBRACE)
		throw Exception("MD5Model::readBoundsEl(): expected { to follow 'bounds'");

	if (anim.numFrames != int(anim.frames.size()))
		throw Exception("MD5Model::readBoundsEl(): frames must be allocated before setting bounds");

	// read in bound for each frame
	for (int i = 0; i < anim.numFrames; i++) {
		readVec(fin, anim.frames[i].min, 3);
		readVec(fin, anim.frames[i].max, 3);
	}

	// next token must be a closing brace }
	t = getNextToken(fin);

	if (TOKEN_LPAREN == t)
		throw Exception("MD5Model::readBoundsEl(): number of bounds exceeds number of frames");

	// expect a closing brace } to end block
	if (t != TOKEN_RBRACE)
		throw Exception("MD5Model::readBoundsEl(): expected }");
}
void MD5Model::readBaseframeEl(std::ifstream &fin, Anim &anim) {
	TOKEN t = getNextToken(fin);

	// expect an opening brace { to begin block
	if (t != TOKEN_LBRACE)
		throw Exception("MD5Model::readBaseframeEl(): expected { to follow 'baseframe'");

	anim.baseJoints.resize(numJoints);

	int i;
	for (i = 0; i < numJoints; i++) {
		// read in joint position
		readVec(fin, anim.baseJoints[i].pos, 3);

		// read in first 3 components of quaternion (must compute 4th)
		float quat[3];
		readVec(fin, quat, 3);

		anim.baseJoints[i].quat = buildQuat(quat[0], quat[1], quat[2]);
	}

	if (i < numJoints - 1)
		throw Exception("MD5Model::readBaseframeEl(): not enough joints");

	// next token must be a closing brace }
	t = getNextToken(fin);

	if (TOKEN_LPAREN == t)
		throw Exception("MD5Model::readBaseframeEl(): too many joints");

	// expect a closing brace } to end block
	if (t != TOKEN_RBRACE)
		throw Exception("MD5Model::readBaseframeEl(): expected }");
}
void MD5Model::readJointsEl(std::ifstream &fin) {
	// make sure numJoints has been set
	if (numJoints <= 0)
		throw Exception("MD5Model::readJointsEl(): numJoints needs to be set before 'joints' block");

	TOKEN t = getNextToken(fin);

	// expect an opening brace { to begin block of joints
	if (t != TOKEN_LBRACE)
		throw Exception("MD5Model::readJointsEl(): expected { to follow 'joints'");

	// read in each joint in block until '}' is hit
	// (if EOF is reached before this, then the read*() methods
	//  will close the file and throw an exception)
	std::string str;
	t = getNextToken(fin, &str);
	while (t != TOKEN_RBRACE) {
		Joint joint;

		// token should be name of joint (a string)
		if (t != TOKEN_STRING)
			throw Exception("MD5Model::readJointsEl(): expected joint name (string)'");

		// read in index of parent joint
		int parentIndex = readInt(fin);

		// read in joint position
		readVec(fin, joint.pos, 3);

		// read in first 3 components of quaternion (must compute 4th)
		float quat[4];
		readVec(fin, quat, 3);

		// 根据1.0f - x*x - y*y - z*z;计算出w
		joint.quat = buildQuat(quat[0], quat[1], quat[2]);

		// add index to parent's list of child joints (if it has a parent,
		// root joints have parent index -1)
		if (parentIndex >= 0) {
			if (size_t(parentIndex) >= joints.size())
				throw Exception("MD5Model::readJointsEl(): parent index is invalid");

			joints[parentIndex].children.push_back(int(joints.size()));
		}

		// add joint to vector of joints
		joints.push_back(joint);

		// get next token
		t = getNextToken(fin, &str);
	}
}
Beispiel #4
0
void DiffuseMaterial::loadMaterialFromXML(const ConfigManager* cm, xml_node<>* node)
{
	if(node->first_node("color"))
		tex.setColor(readVec(node->first_node("color")->value()));
	if(node->first_node("Texture"))
		tex.loadTextureFromXML(cm, node->first_node("Texture"));
}
Beispiel #5
0
void GlossyMaterial::loadMaterialFromXML(const ConfigManager* cm, xml_node<>* node)
{
	if(node->first_node("color"))
		setColor(readVec(node->first_node("color")->value()));
	if(node->first_node("coeff"))
		setCoeff(atof(node->first_node("coeff")->value()));
	if(node->first_node("ColorTexture"))
		colorTex.loadTextureFromXML(cm, node->first_node("ColorTexture"));
	if(node->first_node("CoeffTexture"))
		coeffTex.loadTextureFromXML(cm, node->first_node("CoeffTexture"));
}
void teleop_tracking::StlLoader::parseFile(const std::string &file)
{
  std::ifstream ifile (file.c_str(), std::ios::binary);
  if (!ifile)
    throw std::runtime_error(file);

  ifile.exceptions ( std::ifstream::failbit | std::ifstream::badbit );

  // Read header
  char header_buff[80];
  ifile.read(header_buff, 80);

  // Read n triangles
  char n_buff[4];
  ifile.read(n_buff, 4);

  // copy into local var
  uint32_t n_triangles;
  std::memcpy(&n_triangles, n_buff, 4);

  // Iterate over triangles
  facets_.reserve(n_triangles);
  for (uint32_t i = 0; i < n_triangles; ++i)
  {
    Facet f;
    // read normal
    readVec(ifile, f.normal);
    readVec(ifile, f.vertices[0]);
    readVec(ifile, f.vertices[1]);
    readVec(ifile, f.vertices[2]);
    char endbuff[2];
    ifile.read(endbuff, 2);

    facets_.push_back(f);
  }

}
Beispiel #7
0
int main(int argc, char** argv) {
    FILE* fp;
    if(argc != 2) {
        printf("USAGE: NotSoClever <fileContainingTestVectors>\n");
        return 1;
    }
    fp = fopen(argv[1], "r");
    if(fp == NULL) {
        printf("Failed to open the input file '%s' for reading!\n", argv[1]);
        return 2;
    }
    while(!feof(fp)) {
        std::vector<int> vec;
        int count = readVec(vec, fp);
        if(count <= 0) {
            continue;
        }
        stupidSort(vec, count);
        print(vec);
    }
    fclose(fp);
    return 0;
}
Beispiel #8
0
int ReadHyperMesh::compute(const char *)
{

    // compute parameters
    if ((file = fopen(fileName->getValue(), "r")) <= 0)
    {
        sendError("ERROR: can't open file %s", fileName->getValue());
        return FAIL;
    }
    pushedBack = false;
    //xPoints.reserve(1000);
    //yPoints.reserve(1000);
    //zPoints.reserve(1000);
    vertices.reserve(1000);
    xPoints.clear();
    yPoints.clear();
    zPoints.clear();
    vertices.clear();
    elements.clear();
    types.clear();

    coRestraint sel;
    // Get the selection
    const char *selection;
    // Covise::get_string_param("Selection",&selection);
    selection = p_Selection->getValue();
    sel.add(selection);

    numberOfTimesteps = 0;
    numPoints = 0;
    numVert = 0;
    numElem = 0;
    subdivide = subdivideParam->getValue();
    while (!feof(file))
    {
        getLine();
        if (strncmp(c, "*component(", 11) == 0) // skip unselected components
        {
            int componentID;
            sscanf(c + 11, "%d", &componentID);
            while (*c && (*c != '"'))
                c++;
            if (*c)
            {
                c++;
                const char *componentName = c;
                while (*c && (*c != '"'))
                    c++;
                if (*c == '"')
                {
                    *c = '\0';
                }
                sendInfo("component %d %s\n", componentID, componentName);
            }
            while (!feof(file) && !sel(componentID))
            {
                getLine();
                if (strncmp(c, "*component(", 11) == 0)
                {
                    sscanf(c + 11, "%d", &componentID);
                    while (*c && (*c != '"'))
                        c++;
                    if (*c)
                    {
                        c++;
                        const char *componentName = c;
                        while (*c && (*c != '"'))
                            c++;
                        if (*c == '"')
                        {
                            *c = '\0';
                        }
                        sendInfo("component %d %s\n", componentID, componentName);
                    }
                }
            }
        }
        if (strncmp(c, "*tetra10(", 9) == 0)
        { // new line node
            int tetNum;
            int vert[10];
            int iret = sscanf(c + 9, "%d,1,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", &tetNum, vert, vert + 1, vert + 2, vert + 3, vert + 4, vert + 5, vert + 6, vert + 7, vert + 8, vert + 9);
            if (iret != 11)
            {
                cerr << "parse error reading tetra10 " << iret << endl;
                break;
            }
            if (subdivide)
            {
                if (types.capacity() < (numElem - 20))
                {
                    types.reserve(types.capacity() + 1000);
                }
                elements.push_back(numVert);
                types[numElem] = TYPE_TETRAHEDER;
                numElem++;
                elements.push_back(elements[numElem - 1] + 4);
                types[numElem] = TYPE_TETRAHEDER;
                numElem++;
                elements.push_back(elements[numElem - 1] + 4);
                types[numElem] = TYPE_TETRAHEDER;
                numElem++;
                elements.push_back(elements[numElem - 1] + 4);
                types[numElem] = TYPE_TETRAHEDER;
                numElem++;
                elements.push_back(elements[numElem - 1] + 4);
                types[numElem] = TYPE_PYRAMID;
                numElem++;
                elements.push_back(elements[numElem - 1] + 5);
                types[numElem] = TYPE_PYRAMID;
                numElem++;

                vertices.push_back(vert[4] - 1);
                numVert++;
                vertices.push_back(vert[7] - 1);
                numVert++;
                vertices.push_back(vert[6] - 1);
                numVert++;
                vertices.push_back(vert[0] - 1);
                numVert++;

                vertices.push_back(vert[4] - 1);
                numVert++;
                vertices.push_back(vert[5] - 1);
                numVert++;
                vertices.push_back(vert[8] - 1);
                numVert++;
                vertices.push_back(vert[1] - 1);
                numVert++;

                vertices.push_back(vert[5] - 1);
                numVert++;
                vertices.push_back(vert[6] - 1);
                numVert++;
                vertices.push_back(vert[9] - 1);
                numVert++;
                vertices.push_back(vert[2] - 1);
                numVert++;

                vertices.push_back(vert[7] - 1);
                numVert++;
                vertices.push_back(vert[8] - 1);
                numVert++;
                vertices.push_back(vert[9] - 1);
                numVert++;
                vertices.push_back(vert[3] - 1);
                numVert++;

                //innen pyramids

                vertices.push_back(vert[8] - 1);
                numVert++;
                vertices.push_back(vert[7] - 1);
                numVert++;
                vertices.push_back(vert[6] - 1);
                numVert++;
                vertices.push_back(vert[5] - 1);
                numVert++;
                vertices.push_back(vert[4] - 1);
                numVert++;

                vertices.push_back(vert[5] - 1);
                numVert++;
                vertices.push_back(vert[6] - 1);
                numVert++;
                vertices.push_back(vert[7] - 1);
                numVert++;
                vertices.push_back(vert[8] - 1);
                numVert++;
                vertices.push_back(vert[9] - 1);
                numVert++;
            }
            else
            {
                elements.push_back(numVert);
                types.push_back(TYPE_TETRAHEDER);
                int i;
                for (i = 0; i < 4; i++)
                {
                    vertices.push_back(vert[i] - 1);
                    numVert++;
                }
                numElem++;
            }
        }
        if (strncmp(c, "*hexa20(", 8) == 0)
        { // new line node
            int tetNum;
            int vert[20];
            int iret = sscanf(c + 8, "%d,1,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d,%d", &tetNum, vert, vert + 1, vert + 2, vert + 3, vert + 4, vert + 5, vert + 6, vert + 7, vert + 8, vert + 9, vert + 10, vert + 11, vert + 12, vert + 13, vert + 14, vert + 15, vert + 16, vert + 17, vert + 18, vert + 19);
            if (iret != 21)
            {
                cerr << "parse error reading hexa20 " << iret << endl;
                break;
            }
            if (subdivide)
            {
                if (types.capacity() < (numElem - 20))
                {
                    types.reserve(types.capacity() + 1000);
                }
                elements.push_back(numVert);
                types[numElem] = TYPE_HEXAEDER;
                numElem++;
                elements.push_back(elements[numElem - 1] + 8);
                types[numElem] = TYPE_PYRAMID;
                numElem++;
                elements.push_back(elements[numElem - 1] + 5);
                types[numElem] = TYPE_PYRAMID;
                numElem++;
                elements.push_back(elements[numElem - 1] + 5);
                types[numElem] = TYPE_PYRAMID;
                numElem++;
                elements.push_back(elements[numElem - 1] + 5);
                types[numElem] = TYPE_PYRAMID;
                numElem++;
                elements.push_back(elements[numElem - 1] + 5);
                types[numElem] = TYPE_TETRAHEDER;
                numElem++;
                elements.push_back(elements[numElem - 1] + 4);
                types[numElem] = TYPE_TETRAHEDER;
                numElem++;
                elements.push_back(elements[numElem - 1] + 4);
                types[numElem] = TYPE_TETRAHEDER;
                numElem++;
                elements.push_back(elements[numElem - 1] + 4);
                types[numElem] = TYPE_TETRAHEDER;
                numElem++;
                elements.push_back(elements[numElem - 1] + 4);
                types[numElem] = TYPE_TETRAHEDER;
                numElem++;
                elements.push_back(elements[numElem - 1] + 4);
                types[numElem] = TYPE_TETRAHEDER;
                numElem++;
                elements.push_back(elements[numElem - 1] + 4);
                types[numElem] = TYPE_TETRAHEDER;
                numElem++;
                elements.push_back(elements[numElem - 1] + 4);
                types[numElem] = TYPE_TETRAHEDER;
                numElem++;

                // hex
                vertices.push_back(vert[8] - 1);
                numVert++;
                vertices.push_back(vert[9] - 1);
                numVert++;
                vertices.push_back(vert[10] - 1);
                numVert++;
                vertices.push_back(vert[11] - 1);
                numVert++;
                vertices.push_back(vert[16] - 1);
                numVert++;
                vertices.push_back(vert[17] - 1);
                numVert++;
                vertices.push_back(vert[18] - 1);
                numVert++;
                vertices.push_back(vert[19] - 1);
                numVert++;

                //pyramids
                vertices.push_back(vert[8] - 1);
                numVert++;
                vertices.push_back(vert[16] - 1);
                numVert++;
                vertices.push_back(vert[19] - 1);
                numVert++;
                vertices.push_back(vert[11] - 1);
                numVert++;
                vertices.push_back(vert[12] - 1);
                numVert++;

                vertices.push_back(vert[8] - 1);
                numVert++;
                vertices.push_back(vert[9] - 1);
                numVert++;
                vertices.push_back(vert[17] - 1);
                numVert++;
                vertices.push_back(vert[16] - 1);
                numVert++;
                vertices.push_back(vert[13] - 1);
                numVert++;

                vertices.push_back(vert[9] - 1);
                numVert++;
                vertices.push_back(vert[10] - 1);
                numVert++;
                vertices.push_back(vert[18] - 1);
                numVert++;
                vertices.push_back(vert[17] - 1);
                numVert++;
                vertices.push_back(vert[14] - 1);
                numVert++;

                vertices.push_back(vert[10] - 1);
                numVert++;
                vertices.push_back(vert[11] - 1);
                numVert++;
                vertices.push_back(vert[19] - 1);
                numVert++;
                vertices.push_back(vert[18] - 1);
                numVert++;
                vertices.push_back(vert[15] - 1);
                numVert++;

                // tetrahedra

                vertices.push_back(vert[11] - 1);
                numVert++;
                vertices.push_back(vert[8] - 1);
                numVert++;
                vertices.push_back(vert[12] - 1);
                numVert++;
                vertices.push_back(vert[0] - 1);
                numVert++;

                vertices.push_back(vert[12] - 1);
                numVert++;
                vertices.push_back(vert[16] - 1);
                numVert++;
                vertices.push_back(vert[19] - 1);
                numVert++;
                vertices.push_back(vert[4] - 1);
                numVert++;

                vertices.push_back(vert[8] - 1);
                numVert++;
                vertices.push_back(vert[9] - 1);
                numVert++;
                vertices.push_back(vert[13] - 1);
                numVert++;
                vertices.push_back(vert[1] - 1);
                numVert++;

                vertices.push_back(vert[13] - 1);
                numVert++;
                vertices.push_back(vert[17] - 1);
                numVert++;
                vertices.push_back(vert[16] - 1);
                numVert++;
                vertices.push_back(vert[5] - 1);
                numVert++;

                vertices.push_back(vert[9] - 1);
                numVert++;
                vertices.push_back(vert[10] - 1);
                numVert++;
                vertices.push_back(vert[14] - 1);
                numVert++;
                vertices.push_back(vert[2] - 1);
                numVert++;

                vertices.push_back(vert[17] - 1);
                numVert++;
                vertices.push_back(vert[14] - 1);
                numVert++;
                vertices.push_back(vert[18] - 1);
                numVert++;
                vertices.push_back(vert[6] - 1);
                numVert++;

                vertices.push_back(vert[10] - 1);
                numVert++;
                vertices.push_back(vert[11] - 1);
                numVert++;
                vertices.push_back(vert[15] - 1);
                numVert++;
                vertices.push_back(vert[3] - 1);
                numVert++;

                vertices.push_back(vert[15] - 1);
                numVert++;
                vertices.push_back(vert[19] - 1);
                numVert++;
                vertices.push_back(vert[18] - 1);
                numVert++;
                vertices.push_back(vert[7] - 1);
                numVert++;
            }
            else
            {

                elements[numElem] = numVert;
                types[numElem] = TYPE_HEXAEDER;
                int i;
                for (i = 0; i < 8; i++)
                {
                    vertices.push_back(vert[i] - 1);
                    numVert++;
                }
                numElem++;
            }
        }
        if (strncmp(c, "*node(", 6) == 0)
        { // new line node
            int nodeNum;
            float xc, yc, zc;
            int iret = sscanf(c + 6, "%d,%f,%f,%f", &nodeNum, &xc, &yc, &zc);
            if (iret != 4)
            {
                cerr << "parse error reading node " << iret << endl;
                break;
            }
            if ((numPoints % 1000) == 0)
            {
                xPoints.reserve(xPoints.capacity() + 1000);
                yPoints.reserve(yPoints.capacity() + 1000);
                zPoints.reserve(zPoints.capacity() + 1000);
            }
            if (nodeNum > xData.capacity())
            {
                xPoints[nodeNum - 1] = xc;
                yPoints[nodeNum - 1] = yc;
                zPoints[nodeNum - 1] = zc;
            }
            else
            {
                fprintf(stderr, "error reading coordinates.\n");
                return STOP_PIPELINE;
            }
            numPoints++;
        }
    }

    fclose(file);

    xData.reserve(numPoints);
    yData.reserve(numPoints);
    zData.reserve(numPoints);
    coDoUnstructuredGrid *gridObj;
    // construct the output grid
    if (numPoints)
    {
        char buf[1000];
        sprintf(buf, "%s_Grid", mesh->getObjName());
        gridObj = new coDoUnstructuredGrid(buf, numElem, numVert, numPoints, &elements[0], &vertices[0], &xPoints[0], &yPoints[0], &zPoints[0], &types[0]);
    }
    else
    {
        sendError("could not read points from file %s", fileName->getValue());
        return FAIL;
    }

    if ((file = fopen(resultsFileName->getValue(), "r")) <= 0)
    {
        sendError("ERROR: can't open file %s", resultsFileName->getValue());
        return FAIL;
    }

    numTimeSteps = 0;
    skipped = 0;

    haveDisplacements = false;
    dx = dy = dz = NULL;
    while (!feof(file))
    {
        getLine();
        if (strncmp(c, "SUBCASE", 7) == 0)
        { // new line node
            numData = 0;
            if (skipped < p_skip->getValue())
            {
                skipped++;
                doSkip = true;
                sendInfo("Skipping %d", skipped);
            }
            else
            {
                skipped = 0;
                doSkip = false;
                sendInfo("Reading Timestep %d", numTimeSteps);
            }
            while (!feof(file))
            {
                getLine();
                if (strncmp(c, "RESULTS", 7) == 0)
                {
                    names[numData] = new char[strlen(c + 8) + 1];
                    strcpy(names[numData], c + 8);
                    getLine();

                    char buf[1000];
                    sprintf(buf, "%s_%d_%d", dataPort[numData]->getObjName(), numData, numTimeSteps);
                    if (c[0] == 'V')
                    {
                        pushBack();
                        dataObjects[numData][numTimeSteps] = readVec(buf);
                    }
                    else if (c[0] == 'S')
                    {
                        pushBack();
                        dataObjects[numData][numTimeSteps] = readScal(buf);
                    }
                    else if (strncmp(c, "DISPLACE", 8) == 0) // vector
                    {
                        pushBack();
                        dataObjects[numData][numTimeSteps] = readVec(buf);
                    }
                    else if (strncmp(c, "NSTRESS", 7) == 0) // scalar
                    {
                        pushBack();
                        dataObjects[numData][numTimeSteps] = readScal(buf);
                    }
                    numData++;
                }
                else if (strncmp(c, "SUBCASE", 7) == 0) // new timestep, so quit this loop
                {
                    pushBack();
                    break;
                }
            }
            if (dataObjects[0][numTimeSteps]) // if we actually have data for this timestep go to next timestep
                numTimeSteps++;
        }
        if (numTimeSteps >= p_numt->getValue())
            break;
    }
    fclose(file);
    int n;
    int i;
    for (n = 0; n < numData; n++)
    {
        sendInfo("DataValue %d :%s", n, names[n]);
        coDistributedObject **dataObjs = new coDistributedObject *[numTimeSteps + 1];
        for (i = 0; i < numTimeSteps; i++)
        {
            dataObjs[i] = dataObjects[n][i];
        }
        dataObjs[numTimeSteps] = NULL;
        coDoSet *dataSet = new coDoSet(dataPort[n]->getObjName(), dataObjs);
        if (numTimeSteps > 1)
            dataSet->addAttribute("TIMESTEP", "1 10");
        delete[] dataObjs;
        // Assign sets to output ports:
        dataPort[n]->setCurrentObject(dataSet);
    }
    if (numTimeSteps == 0)
        numTimeSteps = 1;
    coDistributedObject **gridObjects = new coDistributedObject *[numTimeSteps + 1];
    gridObjects[0] = gridObj;
    for (i = 1; i < numTimeSteps; i++)
    {
        if (haveDisplacements)
        {
            char buf[1000];
            sprintf(buf, "%s_Grid_%d", mesh->getObjName(), i);
            coDoVec3 *dataObj = (coDoVec3 *)dataObjects[displacementData][i];
            dataObj->getAddresses(&dx, &dy, &dz);
            int n;
            for (n = 0; n < numPoints; n++) // displaycements are relative to the original point, so add that to the displacements
            {
                dx[n] += xPoints[n];
                dy[n] += yPoints[n];
                dz[n] += zPoints[n];
            }
            gridObj = new coDoUnstructuredGrid(buf, numElem, numVert, numPoints, &elements[0], &vertices[0], dx, dy, dz, &types[0]);
        }
        else
        {
            gridObj->incRefCount();
        }
        gridObjects[i] = gridObj;
    }
    gridObjects[numTimeSteps] = NULL;
    coDoSet *gridSet = new coDoSet(mesh->getObjName(), gridObjects);

    if (numTimeSteps > 1)
        gridSet->addAttribute("TIMESTEP", "1 10");
    delete[] gridObjects;
    // Assign sets to output ports:
    mesh->setCurrentObject(gridSet);

    return SUCCESS;
}
void MD5Model::readMeshEl(std::ifstream &fin) {
	// make sure numMeshes has been set
	if (numMeshes <= 0)
		throw Exception("MD5Model::readMeshesEl(): numMeshes needs to be set before 'mesh' block");

	TOKEN t = getNextToken(fin);

	// expect an opening brace { to begin block of joints
	if (t != TOKEN_LBRACE)
		throw Exception("MD5Model::readMeshEl(): expected { to follow 'mesh'");

	Mesh *mesh = new Mesh;

	// read in all mesh information in block until '}' is hit
	// (if EOF is reached before this, then the read*() methods
	//  will close the file and throw an exception)
	std::string str;
	t = getNextToken(fin, &str);
	while (t != TOKEN_RBRACE) {
		if (str == "vert") {
			// syntax: vert (vertex index) '(' (x) (y) (z) ')' (weight index) (weight count)
			Vertex vert;

			int index = readInt(fin);
			readVec(fin, vert.tc, 2);
			vert.weightIndex = readInt(fin);
			vert.weightCount = readInt(fin);

			// make sure index is within bounds of vector of vertices
			if (size_t(index) >= mesh->verts.size())
				throw Exception("MD5Model::readMeshEl(): vertex index >= numverts");

			mesh->verts[index] = vert;
		}
		else if (str == "tri") {
			// syntax: tri (triangle index) (v0 index) (v1 index) (v2 index)
			Tri tri;

			int index = readInt(fin);

			// make sure index is within bounds of vector of triangles
			if (size_t(index) >= mesh->tris.size())
				throw Exception("MD5Model::readMeshEl(): triangle index >= numtris");

			tri.v[0] = readInt(fin);
			tri.v[1] = readInt(fin);
			tri.v[2] = readInt(fin);
			mesh->tris[index] = tri;
		}
		else if (str == "weight") {
			Weight weight;

			int weightIndex = readInt(fin);
			weight.joint = readInt(fin);
			weight.w = readFloat(fin);
			readVec(fin, weight.pos, 3);

			if (size_t(weightIndex) >= mesh->weights.size())
				throw Exception("MD5Model::readMeshEl(): weight index >= numweights");

			mesh->weights[weightIndex] = weight;
		}
		else if (str == "shader") {
			// 没有使用纹理
			std::string shader;
			if (getNextToken(fin, &shader) != TOKEN_STRING)
				throw Exception("MD5Model::readMeshEl(): expected string to follow 'shader'");
		}
		else if (str == "numverts") {
			if (mesh->verts.size() > 0)
				throw Exception("MD5Model::readMeshEl(): numverts has already been set");

			int n = readInt(fin);

			if (n <= 0)
				throw Exception("MD5Model::readMeshEl(): numverts must be greater than 0");

			mesh->verts.resize(n);
		}
		else if (str == "numtris") {
			if (mesh->tris.size() > 0)
				throw Exception("MD5Model::readMeshEl(): numtris has already been set");

			int n = readInt(fin);

			if (n <= 0)
				throw Exception("MD5Model::readMeshEl(): numtris must be greater than 0");

			mesh->tris.resize(n);
		}
		else if (str == "numweights") {
			if (mesh->weights.size() > 0)
				throw Exception("MD5Model::readMeshEl(): numweights has already been set");

			int n = readInt(fin);

			if (n <= 0)
				throw Exception("MD5Model::readMeshEl(): numweights must be greater than 0");

			mesh->weights.resize(n);
		}

		// read next token
		t = getNextToken(fin, &str);
	}

	meshes.push_back(mesh);
}