第八章:加载Maya2011模型

原文链接:

http://www.rastertek.com/gl40tut08.html

Tutorial 8: Loading Maya 2011 Models

This tutorial will cover how to import static 3D models from Maya 2011. Note that this tutorial will be focused on Maya but it also applies to pretty much any other 3D modeling software
package with some slight changes.

本章将介绍如何导入Maya2011的静态模型。通过稍微修改本章的方法也可以适用于其他3D建模软件。

In the previous tutorials we have already created our own model format and rendered 3D models using that format. The goal now is to convert Maya 2011 models into our format and render
them. I won‘t go into how to model 3D objects in Maya as there are hundreds of tutorials on the net already dedicated to that, we will instead start at the point where you have a textured and triangulated 3D model ready for export.

在前面的教程里,我们已经创建了自己的模型格式用作渲染。现在的目标时将Maya2011的模型转换为自己的模型格式再渲染。本章不会介绍如何使用Maya进行3D建模,这方面已经有太多的教程。我们将从导出已经包含贴图的3D模型开始。

For the Maya export format we will use the .OBJ format as it is easily readable and good for beginners to start with.

我们将使用Maya导出.OBJ格式文件,此格式结构非常简单也很适合初学者。

To export your model in the .obj format you must first enable the .OBJ exporter in Maya. Click "Window", then "Settings/Preferences", then "Plug-in Manager". Scroll down to objExport.mll
and select both "Loaded" and "Auto load". Now to export your model in this format click on "File", then "Export All". Now at the bottom select "Files of type:" and scroll down and select "OBJexport". Give it a file name and hit "Export All" and it will export
it to a text file with a .obj extension. To look at the file you can right click and select Open With and choose WordPad to read the file. You will then see something that looks like the following:

要在Maya中导出.obj格式必须先要激活.OBJ导出工具。点击“Window”,然后“Settings/Preferences”,然后“Plug-in Manager”。找到objExport.mll选择“Loaded”和“Auto load”。下面开始导出,点击“File”,然后“Export All”。在底部的“Files of type:”选择“OBJexport”。填写一个导出的文件名,点击“Export
All”。将导出一个.obj扩展名的文本文件。可以用记事本等文本编辑器打开文件来查看文件的内容。你讲看到类似下面的内容:

Cube.obj

# This file uses centimeters as units for non-parametric coordinates.

mtllib cube.mtl

g default

v -0.500000 -0.500000 0.500000

v 0.500000 -0.500000 0.500000

v -0.500000 0.500000 0.500000

v 0.500000 0.500000 0.500000

v -0.500000 0.500000 -0.500000

v 0.500000 0.500000 -0.500000

v -0.500000 -0.500000 -0.500000

v 0.500000 -0.500000 -0.500000

vt 0.001992 0.001992

vt 0.998008 0.001992

vt 0.001992 0.998008

vt 0.998008 0.998008

vt 0.001992 0.001992

vt 0.998008 0.001992

vt 0.001992 0.998008

vt 0.998008 0.998008

vt 0.001992 0.001992

vt 0.998008 0.001992

vt 0.001992 0.998008

vt 0.998008 0.998008

vt 0.001992 0.001992

vt 0.998008 0.001992

vt 0.001992 0.998008

vt 0.998008 0.998008

vt 0.001992 0.001992

vt 0.998008 0.001992

vt 0.001992 0.998008

vt 0.998008 0.998008

vt 0.998008 0.998008

vt 0.001992 0.998008

vt 0.998008 0.001992

vt 0.001992 0.001992

vn 0.000000 0.000000 1.000000

vn 0.000000 0.000000 1.000000

vn 0.000000 0.000000 1.000000

vn 0.000000 0.000000 1.000000

vn 0.000000 1.000000 0.000000

vn 0.000000 1.000000 0.000000

vn 0.000000 1.000000 0.000000

vn 0.000000 1.000000 0.000000

vn 0.000000 0.000000 -1.000000

vn 0.000000 0.000000 -1.000000

vn 0.000000 0.000000 -1.000000

vn 0.000000 0.000000 -1.000000

vn 0.000000 -1.000000 0.000000

vn 0.000000 -1.000000 0.000000

vn 0.000000 -1.000000 0.000000

vn 0.000000 -1.000000 0.000000

vn 1.000000 0.000000 0.000000

vn 1.000000 0.000000 0.000000

vn 1.000000 0.000000 0.000000

vn 1.000000 0.000000 0.000000

vn -1.000000 0.000000 0.000000

vn -1.000000 0.000000 0.000000

vn -1.000000 0.000000 0.000000

vn -1.000000 0.000000 0.000000

s 1

g pCube1

usemtl file1SG

f 1/1/1 2/2/2 3/3/3

f 3/3/3 2/2/2 4/4/4

s 2

f 3/13/5 4/14/6 5/15/7

f 5/15/7 4/14/6 6/16/8

s 3

f 5/21/9 6/22/10 7/23/11

f 7/23/11 6/22/10 8/24/12

s 4

f 7/17/13 8/18/14 1/19/15

f 1/19/15 8/18/14 2/20/16

s 5

f 2/5/17 8/6/18 4/7/19

f 4/7/19 8/6/18 6/8/20

s 6

f 7/9/21 1/10/22 5/11/23

f 5/11/23 1/10/22 3/12/24

This particular .OBJ model file represents a 3D cube. It has 8 vertices, 24 texture coordinates and normal vectors, and 6 sides made up of 12 faces in total. When examining the file
you can ignore every line unless it starts with a "V", "VT", "VN", or "F". The extra information in the file will not be needed for converting .obj to our file format. Lets look at what each of the important lines means:

这个.OBJ文件描述了一个3D盒子。包含8个顶点,24个纹理坐标和法向量,由12个三角形面组成6个矩形面。

1. The "V" lines are for the vertices. The cube is made up of 8 vertices for the eight corners of the cube. Each is listed in X, Y, Z float format.

1. “V”开头的行表示顶点。盒子由8个顶点组成,每个顶点都包含3个浮点数表示x, y, z。

2. The "VT" lines are for the texture coordinates. The cube is has 24 texture coordinates and most of them are duplicated since it records them for every vertex in every triangle in
the cube model. They are listed in TU, TV float format.

2. “VT”开头的行表示纹理坐标。盒子包含24个纹理坐标,对应盒子的每个三角形的每个顶点。每个纹理坐标包含2个浮点数tu, tv。

3. The "VN" lines are for the normal vectors. The cube is has 24 normal vectors and most of them are duplicated again since it records them for every vertex in every triangle in the
cube model. They are listed in NX, NY, NZ float format.

3. “VN”开头的行表示法向量。盒子包含24个法向量,对应模型的每个三角形的每个顶点。每个法向量包含3个浮点数nx, ny, nz。

4. The "F" lines are for each triangle (face) in the cube model. The values listed are indexes into the vertices, texture coordinates, and normal vectors. The format of each face is:

4. “F”开头的行表示盒子模型的三角形面。使用的是顶点的索引,纹理坐标的索引,法向量索引。格式如下:

f Vertex1/Texture1/Normal1 Vertex2/Texture2/Normal2 Vertex3/Texture3/Normal3

So a line that says "f 3/13/5 4/14/6 5/15/7" then translates to "Vertex3/Texture13/Normal5 Vertex4/Texture14/Normal6 Vertex5/Texture15/Normal7".

"f 3/13/5 4/14/6 5/15/7"意味着“顶点3/纹理坐标13/法向量5 顶点4/纹理坐标14/法向量6 顶点5/纹理坐标15/法向量7”。

The order the data is listed in the .obj file is very important. For example the first vertex in the file corresponds to Vertex1 in the face list. This is the same for texture coordinates
and normals as well.

obj文件里的数据顺序非常重要。例如第一个顶点对应三角形面列表里的顶点1。纹理坐标和法向量也是类似的规则。

Looking at the face lines in the .obj file notice that the three index groups per line make an individual triangle. And in the case of this cube model the 12 total faces make up the
6 sides of the cube that has 2 triangles per side.

obj文件里每一个“f”行定义了一个三角形面。本章的盒子由12个三角形面组成。

Right hand to Left hand conversion

左右手坐标系转换

By default Maya 2011 is a right handed coordinate system and exports the .obj file data in right hand coordinates. To convert that data into a left handed system which we have setup
OpenGL 4.0 as you have to do the following:

Maya2011模式使用右手坐标系,导出的obj文件也同样基于右手坐标系。要转换obj数据到OpenGL 4.0左手坐标系我们需要做如下操作:

1. Invert the Z coordinate vertices. In the code you will see it do this: vertices[vertexIndex].z = vertices[vertexIndex].z * -1.0f;

1. 转换顶点Z坐标。在代码里需要这样做:vertices[vertexIndex].z = vertices[vertexIndex].z * -1.0f;

2. Invert the TV texture coordinate. In the code you will see it do this: texcoords[texcoordIndex].y = 1.0f - texcoords[texcoordIndex].y;

2. 转换纹理TV坐标。在代码里需要这样做:texcoords[texcoordIndex].y = 1.0f - texcoords[texcoordIndex].y;

3. Invert the NZ normal vertex. In the code you will see it do this: normals[normalIndex].z = normals[normalIndex].z * -1.0f;

3. 转换法向量NZ坐标。在代码里需要这样做:normals[normalIndex].z = normals[normalIndex].z * -1.0f;

4. Convert the drawing order from counter clockwise to clockwise. In the code I simply read in the indexes in reverse order instead of re-organizing it after the fact:

4. 将绘制顺序从逆时针转换为顺时针。在代码里我调整了读取索引的顺序二不是重新构造数据:

fin >> faces[faceIndex].vIndex3 >> input2 >> faces[faceIndex].tIndex3 >> input2 >> faces[faceIndex].nIndex3;

fin >> faces[faceIndex].vIndex2 >> input2 >> faces[faceIndex].tIndex2 >> input2 >> faces[faceIndex].nIndex2;

fin >> faces[faceIndex].vIndex1 >> input2 >> faces[faceIndex].tIndex1 >> input2 >> faces[faceIndex].nIndex1;

With those four steps complete the model data will be ready for our OpenGL 4.0 setup to render correctly.

经过上面4步,OpenGL 4.0就可以正确处理模型数据用于渲染了。

Main.cpp

The program to convert the Maya 2011 .obj files into our OpenGL 4.0 format is fairly simple and is a single program file called main.cpp. It opens a command prompt and asks for the
name of the .obj file to convert. Once the user types in the name it will attempt to open the file and read in the data counts and build the structures required to read the data into. After that it reads the data into those structures and converts it to a
left hand system. Once that is done it then writes the data out to a model.txt file. That file can then be renamed and used for rendering in OpenGL 4.0 using the 3D model render project from the previous tutorial.

将Maya2011 .obj文件转换为我们自己的OpenGL 4.0格式的程序的文件为main.cpp。它使用命令窗口并要求输入需要转换的.obj文件名。输入文件名后,程序试图打开文件并读取数据。在读完数据后将数据转换为左手坐标系。完成后将转换后的数据输出到model.txt文件。你可以将文件重命名,并使用前面教程的程序加载并渲染。

////////////////////////////////////////////////////////////////////////////////
// Filename: main.cpp
////////////////////////////////////////////////////////////////////////////////

//////////////
// INCLUDES //
//////////////
#include <iostream>
#include <fstream>
using namespace std;

//////////////
// TYPEDEFS //
//////////////
typedef struct
{
 float x, y, z;
}VertexType;

typedef struct
{
 int vIndex1, vIndex2, vIndex3;
 int tIndex1, tIndex2, tIndex3;
 int nIndex1, nIndex2, nIndex3;
}FaceType;

/////////////////////////
// FUNCTION PROTOTYPES //
/////////////////////////
void GetModelFilename(char*);
bool ReadFileCounts(char*, int&, int&, int&, int&);
bool LoadDataStructures(char*, int, int, int, int);

//////////////////
// MAIN PROGRAM //
//////////////////
int main()
{
 bool result;
 char filename[256];
 int vertexCount, textureCount, normalCount, faceCount;
 char garbage;

 // Read in the name of the model file.
 GetModelFilename(filename);

 // Read in the number of vertices, tex coords, normals, and faces so that the data structures can be initialized with the exact sizes needed.
 result = ReadFileCounts(filename, vertexCount, textureCount, normalCount, faceCount);
 if(!result)
 {
  return -1;
 }

 // Display the counts to the screen for information purposes.
 cout << endl;
 cout << "Vertices: " << vertexCount << endl;
 cout << "UVs:      " << textureCount << endl;
 cout << "Normals:  " << normalCount << endl;
 cout << "Faces:    " << faceCount << endl;

 // Now read the data from the file into the data structures and then output it in our model format.
 result = LoadDataStructures(filename, vertexCount, textureCount, normalCount, faceCount);
 if(!result)
 {
  return -1;
 }

 // Notify the user the model has been converted.
 cout << "\nFile has been converted." << endl;
 cout << "\nDo you wish to exit (y/n)? ";
 cin >> garbage;

 return 0;
}

void GetModelFilename(char* filename)
{
 bool done;
 ifstream fin;

 // Loop until we have a file name.
 done = false;
 while(!done)
 {
  // Ask the user for the filename.
  cout << "Enter model filename: ";

  // Read in the filename.
  cin >> filename;

  // Attempt to open the file.
  fin.open(filename);

  if(fin.good())
  {
   // If the file exists and there are no problems then exit since we have the file name.
   done = true;
  }
  else
  {
   // If the file does not exist or there was an issue opening it then notify the user and repeat the process.
   fin.clear();
   cout << endl;
   cout << "File " << filename << " could not be opened." << endl << endl;
  }
 }

 return;
}

bool ReadFileCounts(char* filename, int& vertexCount, int& textureCount, int& normalCount, int& faceCount)
{
 ifstream fin;
 char input;

 // Initialize the counts.
 vertexCount = 0;
 textureCount = 0;
 normalCount = 0;
 faceCount = 0;

 // Open the file.
 fin.open(filename);

 // Check if it was successful in opening the file.
 if(fin.fail() == true)
 {
  return false;
 }

 // Read from the file and continue to read until the end of the file is reached.
 fin.get(input);
 while(!fin.eof())
 {
  // If the line starts with 'v' then count either the vertex, the texture coordinates, or the normal vector.
  if(input == 'v')
  {
   fin.get(input);
   if(input == ' ') { vertexCount++; }
   if(input == 't') { textureCount++; }
   if(input == 'n') { normalCount++; }
  }

  // If the line starts with 'f' then increment the face count.
  if(input == 'f')
  {
   fin.get(input);
   if(input == ' ') { faceCount++; }
  }

  // Otherwise read in the remainder of the line.
  while(input != '\n')
  {
   fin.get(input);
  }

  // Start reading the beginning of the next line.
  fin.get(input);
 }

 // Close the file.
 fin.close();

 return true;
}

bool LoadDataStructures(char* filename, int vertexCount, int textureCount, int normalCount, int faceCount)
{
 VertexType *vertices, *texcoords, *normals;
 FaceType *faces;
 ifstream fin;
 int vertexIndex, texcoordIndex, normalIndex, faceIndex, vIndex, tIndex, nIndex;
 char input, input2;
 ofstream fout;

 // Initialize the four data structures.
 vertices = new VertexType[vertexCount];
 if(!vertices)
 {
  return false;
 }

 texcoords = new VertexType[textureCount];
 if(!texcoords)
 {
  return false;
 }

 normals = new VertexType[normalCount];
 if(!normals)
 {
  return false;
 }

 faces = new FaceType[faceCount];
 if(!faces)
 {
  return false;
 }

 // Initialize the indexes.
 vertexIndex = 0;
 texcoordIndex = 0;
 normalIndex = 0;
 faceIndex = 0;

 // Open the file.
 fin.open(filename);

 // Check if it was successful in opening the file.
 if(fin.fail() == true)
 {
  return false;
 }

 // Read in the vertices, texture coordinates, and normals into the data structures.
 // Important: Also convert to left hand coordinate system since Maya uses right hand coordinate system.
 fin.get(input);
 while(!fin.eof())
 {
  if(input == 'v')
  {
   fin.get(input);

   // Read in the vertices.
   if(input == ' ')
   {
    fin >> vertices[vertexIndex].x >> vertices[vertexIndex].y >> vertices[vertexIndex].z;

    // Invert the Z vertex to change to left hand system.
    vertices[vertexIndex].z = vertices[vertexIndex].z * -1.0f;
    vertexIndex++;
   }

   // Read in the texture uv coordinates.
   if(input == 't')
   {
    fin >> texcoords[texcoordIndex].x >> texcoords[texcoordIndex].y;

    // Invert the V texture coordinates to left hand system.
    texcoords[texcoordIndex].y = 1.0f - texcoords[texcoordIndex].y;
    texcoordIndex++;
   }

   // Read in the normals.
   if(input == 'n')
   {
    fin >> normals[normalIndex].x >> normals[normalIndex].y >> normals[normalIndex].z;

    // Invert the Z normal to change to left hand system.
    normals[normalIndex].z = normals[normalIndex].z * -1.0f;
    normalIndex++;
   }
  }

  // Read in the faces.
  if(input == 'f')
  {
   fin.get(input);
   if(input == ' ')
   {
    // Read the face data in backwards to convert it to a left hand system from right hand system.
    fin >> faces[faceIndex].vIndex3 >> input2 >> faces[faceIndex].tIndex3 >> input2 >> faces[faceIndex].nIndex3
        >> faces[faceIndex].vIndex2 >> input2 >> faces[faceIndex].tIndex2 >> input2 >> faces[faceIndex].nIndex2
        >> faces[faceIndex].vIndex1 >> input2 >> faces[faceIndex].tIndex1 >> input2 >> faces[faceIndex].nIndex1;
    faceIndex++;
   }
  }

  // Read in the remainder of the line.
  while(input != '\n')
  {
   fin.get(input);
  }

  // Start reading the beginning of the next line.
  fin.get(input);
 }

 // Close the file.
 fin.close();

 // Open the output file.
 fout.open("model.txt");

 // Write out the file header that our model format uses.
 fout << "Vertex Count: " << (faceCount * 3) << endl;
 fout << endl;
 fout << "Data:" << endl;
 fout << endl;

 // Now loop through all the faces and output the three vertices for each face.
 for(int i=0; i<faceIndex; i++)
 {
  vIndex = faces[i].vIndex1 - 1;
  tIndex = faces[i].tIndex1 - 1;
  nIndex = faces[i].nIndex1 - 1;

  fout << vertices[vIndex].x << ' ' << vertices[vIndex].y << ' ' << vertices[vIndex].z << ' '
       << texcoords[tIndex].x << ' ' << texcoords[tIndex].y << ' '
       << normals[nIndex].x << ' ' << normals[nIndex].y << ' ' << normals[nIndex].z << endl;

  vIndex = faces[i].vIndex2 - 1;
  tIndex = faces[i].tIndex2 - 1;
  nIndex = faces[i].nIndex2 - 1;

  fout << vertices[vIndex].x << ' ' << vertices[vIndex].y << ' ' << vertices[vIndex].z << ' '
       << texcoords[tIndex].x << ' ' << texcoords[tIndex].y << ' '
       << normals[nIndex].x << ' ' << normals[nIndex].y << ' ' << normals[nIndex].z << endl;

  vIndex = faces[i].vIndex3 - 1;
  tIndex = faces[i].tIndex3 - 1;
  nIndex = faces[i].nIndex3 - 1;

  fout << vertices[vIndex].x << ' ' << vertices[vIndex].y << ' ' << vertices[vIndex].z << ' '
       << texcoords[tIndex].x << ' ' << texcoords[tIndex].y << ' '
       << normals[nIndex].x << ' ' << normals[nIndex].y << ' ' << normals[nIndex].z << endl;
 }

 // Close the output file.
 fout.close();

 // Release the four data structures.
 if(vertices)
 {
  delete [] vertices;
  vertices = 0;
 }
 if(texcoords)
 {
  delete [] texcoords;
  texcoords = 0;
 }
 if(normals)
 {
  delete [] normals;
  normals = 0;
 }
 if(faces)
 {
  delete [] faces;
  faces = 0;
 }

 return true;
}

Summary

总结

We can now convert Maya 2011 .obj files into our simple model format.

本章介绍了将Maya 2011 .obj文件转换为我们自己的模型格式的方法。

To Do Exercises

练习

1. Recompile the program and run it with the supplied .obj model file.

1. 重新编译并运行代码测试转换.obj模型文件。

2. Create (or have someone else make for you) a Maya 2011 model and export it in .obj format and run this program to convert it.

2. 创建(或通过其他途径获取)一个Maya 2011模型并导出为.obj格式文件,然后运行本章程序进行转换。

3. Convert this code to read in and export a different model format that you might prefer.

3. 修改代码,使它可以读取并导出任何你喜欢的模型格式。

Source Code

源代码

http://www.rastertek.com/gl40src08.zip

时间: 2024-08-25 01:37:32

第八章:加载Maya2011模型的相关文章

Threejs 加载 DAE 模型遇到关题汇总

太阳火神的美丽人生 (http://blog.csdn.net/opengl_es) 本文遵循"署名-非商业用途-保持一致"创作公用协议 转载请保留此句:太阳火神的美丽人生 -  本博客专注于 敏捷开发及移动和物联设备研究:iOS.Android.Html5.Arduino.pcDuino,否则,出自本博客的文章拒绝转载或再转载,谢谢合作. 我们来一起看一个 Threejs 官方的示例: http://threejs.org/examples/#webgl_loader_collada

ceisum_加载倾斜摄影模型

osgb转换为3Dtiles格式(使用工具转换) 然后加载到cesium中(加载代码见下,可以控制模型高度) var offset = function(height,tileset) { console.log(height); height = Number(height); if (isNaN(height)) { return; } var cartographic = Cesium.Cartographic.fromCartesian(tileset.boundingSphere.ce

xBIM 实战01 在浏览器中加载IFC模型文件

一.创建Web项目 打开VS,新建Web项目,选择 .NET Framework 4.5 选择一个空的项目 新建完成后,项目结构如下: 二.添加webServer访问文件类型 由于WexXplorer 加载的是 .wexBIM格式的文件或者文件流,所以需要在Web.config文件中添加如下配置 <system.webServer> <security> <requestFiltering> <requestLimits maxAllowedContentLeng

xBIM 实战02 在浏览器中加载IFC模型文件并设置特效

系列目录    [已更新最新开发文章,点击查看详细] 在模型浏览器中加载模型后,可以对模型做一些特殊操作.下图是常用的设置. 都是通过 xbim-viewer.js 中的 API 来设置以达到一定的效果.代码如下: 1 <!DOCTYPE html> 2 <html> 3 <head> 4 <title>xViewer</title> 5 <meta http-equiv="content-type" content=&

边练边学--plist文件,懒加载,模型初使用--补充instancetype

一.什么是plist文件 1>将数据直接写在代码里面,不是一种合理的做法.如果数据经常修改,就要经常翻开对应的代码进行修改,造成代码扩展性低 2>因此,可以考虑将经常变得数据放在文件中进行存储,程序启动后从文件中读取最新的数据.如果要变动数据,直接修改数据文件即可,不用修改代码 3>一般可以使用属性列表文件存储NSArray或者NSDictionary之类的数据,这种“属性列表文件”的扩展名是plist,因此也成为“plist文件” 二.创建plist文件 三.解析plist文件 代码实

OpenGL学习脚印:模型加载初步-加载obj模型(load obj model)

写在前面 前面介绍了光照基础内容,以及材质和lighting maps,和光源类型,我们对使用光照增强场景真实感有了一定了解.但是到目前为止,我们通过在程序中指定的立方体数据,绘制立方体,看起来还是很乏味.本节开始介绍模型加载,通过加载丰富的模型,能够丰富我们的场景,变得好玩.本节的示例代码均可以在我的github下载. 加载模型可以使用比较好的库,例如obj模型加载的库,Assimp加载库.本节作为入门篇,我们一开始不使用这些库加载很酷的模型,而是熟悉下模型以及模型加载的概念,然后我们封装一个

cesium 加载倾斜摄影模型(这里有一坑)

代码如下: 1 // Construct the default list of terrain sources. 2 var terrainModels = Cesium.createDefaultTerrainProviderViewModels(); 3 4 // Construct the viewer with just what we need for this base application 5 var viewer = new Cesium.Viewer('cesiumCont

机器学习之保存与加载.pickle模型文件

import pickle from sklearn.externals import joblib from sklearn.svm import SVC from sklearn import datasets #定义一个分类器 svm = SVC() iris = datasets.load_iris() X = iris.data y = iris.target #训练模型 svm.fit(X,y) #1.保存成Python支持的文件格式Pickle #在当前目录下可以看到svm.pic

tensorflow加载embedding模型进行可视化

1.功能 采用python的gensim模块训练的word2vec模型,然后采用tensorflow读取模型可视化embedding向量 ps:采用C++版本训练的w2v模型,python的gensim模块读不了. 2.python训练word2vec模型代码 import multiprocessing from gensim.models.word2vec import Word2Vec, LineSentence print('开始训练') train_file = "/tmp/train