游戏开发论坛

 找回密码
 立即注册
搜索
查看: 5537|回复: 9

求解:openGL加载3DS文件的问题

[复制链接]

2

主题

6

帖子

6

积分

新手上路

Rank: 1

积分
6
发表于 2010-8-11 17:32:00 | 显示全部楼层 |阅读模式
众所周知,openGL用3为模型最简单的办法就是加载3ds文件,可是小弟我做的一个程序只能加载一些简单的3ds文件,稍微复杂一点的就加载不进来。就像从网上down下来的汽车模型用3Dmax导出成3DS文件的要不就是贴图不对,要不就是加载不进来,这是为什么啊??就这个文件就加在不进来

2

主题

6

帖子

6

积分

新手上路

Rank: 1

积分
6
 楼主| 发表于 2010-8-11 17:33:00 | 显示全部楼层

Re:求解:openGL加载3DS文件的问题

防止帖子沉了,自己先顶一下

86

主题

2251

帖子

2384

积分

金牌会员

Rank: 6Rank: 6

积分
2384
QQ
发表于 2010-8-11 20:02:00 | 显示全部楼层

Re:求解:openGL加载3DS文件的问题

3DS文件可不是最简单的

2

主题

6

帖子

6

积分

新手上路

Rank: 1

积分
6
 楼主| 发表于 2010-8-11 20:27:00 | 显示全部楼层

Re:求解:openGL加载3DS文件的问题

那什么是最简单的??我见过一种obj的可是不知道怎么用

0

主题

1

帖子

0

积分

新手上路

Rank: 1

积分
0
发表于 2011-4-2 21:24:00 | 显示全部楼层

Re:求解:openGL加载3DS文件的问题

我也不会,想知道

45

主题

1163

帖子

1165

积分

金牌会员

Rank: 6Rank: 6

积分
1165
发表于 2011-4-8 08:59:00 | 显示全部楼层

Re:求解:openGL加载3DS文件的问题

http://dev.gameres.com/Program/Visual/Other/3DSFileFormat.doc

0

主题

5

帖子

5

积分

新手上路

Rank: 1

积分
5
发表于 2011-4-10 16:11:00 | 显示全部楼层

Re: 求解:openGL加载3DS文件的问题

正好在学习,望同大家交流!

使用java写的,请参考!



import com.sun.opengl.util.BufferUtil;
import java.awt.Color;
import java.io.FileInputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.nio.channels.FileChannel;
import java.util.Hashtable;
import java.util.Vector;

public class ThreeDSParser {
    public int len = 0;
    public Vector<Obj> objs = new Vector<Obj>();
    public Hashtable<String,Material> nameMatHt = new Hashtable<String,Material>();
    public Material curMat;
    public Obj curObj;
    public IntBuffer curIndices;
    public FloatBuffer curTexsBuff;
    public IntBuffer trimeshs;
    public int numOfTrimesh;
    public int numOfVertices;
    public float[] camera = new float[9];
    public float[] spot_position = new float[4];
    public float[] spot_direction = new float[4];
    public float maxCutoff , minCutoff;
    public float[] lightColor = new float[4];
    public float[][] material = new float[4][4];
    public float ou, ov, tu=1f,  tv=1f;

   
    public ThreeDSParser(){}
    public  void parseFile(String filename){
        try {
            FileInputStream fis = new FileInputStream(filename);
            FileChannel fc = fis.getChannel();
            ByteBuffer bb = ByteBuffer.allocate((int)fc.size());
            bb = bb.order(ByteOrder.LITTLE_ENDIAN);
            bb.clear();
            fc.read(bb);
            bb.flip();
            
            while (bb.hasRemaining()) {
                int id = bb.getShort() &0xffff;
                int length = bb.getInt();

                switch(id) {
                    case 0x4d4d:
                        //---------------文件的头部---------------//
                        break;
                    case 0x3d3d:
                        //---------------编辑块头部----------------//
                        break;
                    case 0x4000:
                        //----------------对象头部-----------------//
                        //----------------6个字节的对象名称-------------//
                        curObj = new Obj();
                        
                        byte[] b = new byte[6];
                        StringBuilder sb = new StringBuilder();
                        byte t = 0;
                        while((t=bb.get())!=0){
                            sb.append((char)t);
                        }
                        
                        curObj.objName = sb.toString();
                        break;

                    case 0x4100:
                        break;
                    case 0x4110:
                        numOfVertices = bb.getShort();
                        
                        //一个用于存放所有顶点的坐标x, y, z的数组
                        curObj.vertsBuff = BufferUtil.newFloatBuffer(3*numOfVertices);
                        curObj.vertsBuff.clear();

                        //一个用于存放顶点法线坐标的数组
                        curObj.normsBuff = BufferUtil.newFloatBuffer(3*numOfVertices);
                        curObj.normsBuff.clear();

                        for (int j=0;j<numOfVertices;j++){
                            //放入x坐标
                            curObj.vertsBuff.put(bb.getFloat());
                            curObj.normsBuff.put(0.0f);
                            //放入y坐标
                            curObj.vertsBuff.put(bb.getFloat());
                            curObj.normsBuff.put(0.0f);
                            //放入z坐标
                            curObj.vertsBuff.put(bb.getFloat());
                            curObj.normsBuff.put(0.0f);
   
                        }
                        curObj.vertsBuff.flip();
                        curObj.normsBuff.flip();
                        curObj.texsBuff = null;
                        break;
                    case 0x4120:
                        /*================面====================*/
                        numOfTrimesh = bb.getShort()&0xffff;
                        curObj.planeNormsBuff = BufferUtil.newFloatBuffer(3*numOfTrimesh);
                        curObj.planeNormsBuff.clear();
                        trimeshs = BufferUtil.newIntBuffer(3*numOfTrimesh);
                        trimeshs.clear();
                        
                        for (int j=0; j<numOfTrimesh; j++) {
                            //面三个顶点A, B, C的索引
                            int ai = bb.getShort()&0xffff; //A
                            int bi = bb.getShort()&0xffff; //B
                            int ci = bb.getShort()&0xffff; //C
                           
                            trimeshs.put(ai);
                            trimeshs.put(bi);
                            trimeshs.put(ci);

                            //面的三个点坐标用于计算面的法线
                            triNormalVector(ai,bi,ci);

                            //跳过下面一个2个字节的数据
                            bb.position(bb.position()+2);
   
                        }
                        curObj.planeNormsBuff.flip();
                        trimeshs.flip();

                        break;
                    case 0x4130:
                        //----------------面所使用的材质名称-------------------//
                        //---------------先读一个以0结束的字符串--------------//
                        //------接下来读2个字节的使用该材质的面数量------------//
                        //-------------再读2个字节的所有面的索引---------------//
                        StringBuilder sb2 = new StringBuilder();
                        byte t2 = 0;
                        while((t2=bb.get())!=0){
                            sb2.append((char)t2);
                        }
                        String materialName = sb2.toString().trim();
                        
                        curObj.matNames.add(materialName);

                        int num = bb.getShort();
                        curIndices = BufferUtil.newIntBuffer(3*num);
                        curIndices.clear();

                        for (int j=0;j<num;j++) {
                            int i = bb.getShort();
                            int v1 = trimeshs.get(3*i);
                            int v2 = trimeshs.get(3*i + 1);
                            int v3 = trimeshs.get(3*i + 2);
                            curIndices.put(v1);
                            curIndices.put(v2);
                            curIndices.put(v3);

                        }
                        curIndices.flip();
                        curObj.indices.add(curIndices);
                        
                        break;
                    case 0x4140:
                        //-----------------------项点纹理映射坐标----------------//
                        
                        //-----------------------读取顶点数量---------------------//
                        numOfVertices = bb.getShort();
                        
                        //-----------------------用于存放纹理坐标的内存-------------------//
                        curObj.texsBuff = BufferUtil.newFloatBuffer(2*numOfVertices);
                        curObj.texsBuff.clear();
                        
                        //---------------------读纹理坐标--------------//
                        for (int j=0;j<numOfVertices;j++){
                            curObj.texsBuff.put(bb.getFloat());
                            curObj.texsBuff.put(bb.getFloat());
                        }
                        curObj.texsBuff.flip();
                        break;
                    case 0x4160:
                        objs.add(curObj);

                        bb.position(bb.position()+length-6);
                        break;
                    case 0xafff:
                        //-----------------材质头部-----------------//
                        curMat = new Material();
                        break;
                    case 0xa000:
                        //----------------材质的名称------------------//
                        b = new byte[length-6];
                        for (int j=0; j<length-6; j++) {
                            b[j] = bb.get();
                        }
                        String matName = new String(b,"gbk").trim();
                        if( nameMatHt.get(matName) == null )
                            nameMatHt.put(matName, curMat);

                        break;

                    case 0xa200:
                        //-------------------纹理头部-----------------//
                        break;
                    case 0xa300:
                        //-------------------纹理的文件名-------------//
                        b = new byte[length-6];
                        for (int j=0; j<length-6; j++) {
                            b[j] = bb.get();
                        }
                        curMat.texFileName = new String(b,"gbk").trim().toLowerCase();
                        break;
                    case 0xa353:
                        //---------------------纹理偏移值v--------------//
                        curMat.ov = bb.getFloat();

                        break;
                    case 0xa354:
                        //------------------纹理平铺u---------------------//
                        curMat.tu = bb.getFloat();

                        break;
                    case 0xa356:
                        //------------------纹理平铺v---------------------//
                        curMat.tv = bb.getFloat();

                        break;
                    case 0xa358:
                        //------------------纹理偏移值u---------------------//
                        curMat.ou = bb.getFloat();

                        break;  

                    case 0xa010:
                        //--------------------环境光--------------------//
                        bb.position(bb.position()+6);
                        int ar = bb.get()&0xff;
                        int ag = bb.get()&0xff;
                        int ab = bb.get()&0xff;
                        curMat.ambient = new Color(ar,ag,ab, 255).getComponents(null);
                        break;
                    case 0xa020:
                        //---------------------漫射光------------------//
                        bb.position(bb.position()+6);
                        int dr = bb.get()&0xff;
                        int dg = bb.get()&0xff;
                        int db = bb.get()&0xff;
                        curMat.diffuse = new Color(dr,dg,db, 255).getComponents(null);
                       
                        break;
                    case 0xa030:
                        //-------------高光反射----------------------//
                        bb.position(bb.position()+6);
                        int sr = bb.get()&0xff;
                        int sg = bb.get()&0xff;
                        int sbb = bb.get()&0xff;
                        curMat.specular = new Color(sr,sg,sbb, 255).getComponents(null);
                        
                        break;

                    case 0xa041:
                        //-------------------光泽度--------------------//
                        bb.position(bb.position()+6);
                        curMat.shininess =  bb.get()&0xff;
                        bb.position(bb.position()+1);
                        break;
                     case 0x4600:
                        //------------------光源的位置坐标-----------------//
                         spot_position[0] = bb.getFloat(); //光源的位置x
                         spot_position[1] = bb.getFloat(); //光源的位置y
                         spot_position[2] = bb.getFloat(); //光源的位置z
                         spot_position[3] = 1.0f;
                         break;
                     case 0x4610:
                         //------------------光源的目标位置坐标(xref,yref,zref)-----------------//
                         spot_direction[0] = bb.getFloat();
                         spot_direction[1] = bb.getFloat();
                         spot_direction[2] = bb.getFloat();
                  
//                         spot_direction[0] -= spot_position[0];
//                         spot_direction[1] -= spot_position[1];
//                         spot_direction[2] -= spot_position[2];
                         spot_direction[3] = 1.0f;
                         minCutoff = bb.getFloat()/2.0f; //截止角
                         maxCutoff = bb.getFloat()/2.0f;
                         bb.position(bb.position()+length-6-20);
                         break;
                     case 0x10:
                         //---------------光源的颜色------------------------//
                         new Color(bb.getFloat(),bb.getFloat(),bb.getFloat(),1.0f).getComponents(lightColor);
                         break;
                     case 0x4700:
                         camera[0] = bb.getFloat(); //观察点x0
                         camera[1] = bb.getFloat(); //观察点y0
                         camera[2] = bb.getFloat(); //观察点z0
                         camera[3] = bb.getFloat(); //瞄准点xref
                         camera[4] = bb.getFloat(); //瞄准点yref
                         camera[5] = bb.getFloat(); //瞄准点zref
                        
                         //跳过下面一个4个字节的数据
                         bb.position(bb.position()+4);
                         camera[6] = bb.getFloat(); //相机的视角
                         break;
                     case 0x4720:
                         camera[7] = bb.getFloat(); //近点
                         camera[8] = bb.getFloat(); //远点
                         break;
             break;
                    default:
                        bb.position(bb.position()+length-6);

                }
            }
        } catch (Exception e){
            e.printStackTrace();
            System.exit(1);
        }
    }
   
    public void triNormalVector(int ai, int bi, int ci){
        float[] v1 = new float[3];
        float[] v2 = new float[3];
        float[] v3 = new float[3];
        
        v1[0] = curObj.vertsBuff.get(3*ci) - curObj.vertsBuff.get(3*bi);
        v1[1] = curObj.vertsBuff.get(3*ci+1) - curObj.vertsBuff.get(3*bi+1);
        v1[2] = curObj.vertsBuff.get(3*ci+2) - curObj.vertsBuff.get(3*bi+2);
        
        v2[0] = curObj.vertsBuff.get(3*ai) - curObj.vertsBuff.get(3*bi);
        v2[1] = curObj.vertsBuff.get(3*ai+1) - curObj.vertsBuff.get(3*bi+1);
        v2[2] = curObj.vertsBuff.get(3*ai+2) - curObj.vertsBuff.get(3*bi+2);
        
        v3[0] = v1[1]*v2[2] - v1[2]*v2[1];
        v3[1] = v1[2]*v2[0] - v1[0]*v2[2];
        v3[2] = v1[0]*v2[1] - v1[1]*v2[0];
      

        
        curObj.planeNormsBuff.put(v3[0]);
        curObj.planeNormsBuff.put(v3[1]);
        curObj.planeNormsBuff.put(v3[2]);
        
        //同原来这三个顶点的法向量进行矢量和
        
        //a点的法线(x,y,z)
        curObj.normsBuff.put(3*ai,curObj.normsBuff.get(3*ai)+v3[0]);
        curObj.normsBuff.put(3*ai+1,curObj.normsBuff.get(3*ai+1)+v3[1]);        
        curObj.normsBuff.put(3*ai+2,curObj.normsBuff.get(3*ai+2)+v3[2]);
//        
//        b点的法线(x,y,z)
        curObj.normsBuff.put(3*bi,curObj.normsBuff.get(3*bi)+v3[0]);
        curObj.normsBuff.put(3*bi+1,curObj.normsBuff.get(3*bi+1)+v3[1]);        
        curObj.normsBuff.put(3*bi+2,curObj.normsBuff.get(3*bi+2)+v3[2]);
//        
//        c点的法线(x,y,z)
        curObj.normsBuff.put(3*ci,curObj.normsBuff.get(3*ci)+v3[0]);
        curObj.normsBuff.put(3*ci+1,curObj.normsBuff.get(3*ci+1)+v3[1]);        
        curObj.normsBuff.put(3*ci+2,curObj.normsBuff.get(3*ci+2)+v3[2]);
  
    }
}

public class Material {
    public float[] ambient  = new float[3];
    public float[] diffuse = new float[3];
    public float[] specular = new float[3];
    public float shininess;
    public String texFileName = null;
    float ou = 0f;
    float tu = 1.0f;
    float ov = 0f;
    float tv = 1.0f;
}

import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.Vector;


public class Obj {
        public String objName;
        public Vector<String> matNames = new Vector<String>();
        public FloatBuffer vertsBuff;
        public FloatBuffer normsBuff;
        public FloatBuffer  texsBuff;
        public Vector<IntBuffer>  indices = new Vector<IntBuffer>();
        public FloatBuffer planeNormsBuff;
}

public void reshape(GLAutoDrawable drawable, int x, int y, int w, int h){
        GL gl = drawable.getGL();
        GLU glu = new GLU();
        gl.glViewport(x, y, w, h);
        gl.glMatrixMode(GL.GL_PROJECTION);
        gl.glLoadIdentity();
        glu.gluPerspective(p.camera[6], w/h, 0.1, 10000);
        gl.glMatrixMode(GL.GL_MODELVIEW);
        gl.glLoadIdentity();
        glu.gluLookAt(p.camera[0], p.camera[1], p.camera[2], p.camera[3], p.camera[4], p.camera[5], 0, 0, 1);
        
    }
public void display(GLAutoDrawable drawable){
        GL gl = drawable.getGL();
        gl.glClear(GL.GL_COLOR_BUFFER_BIT | GL.GL_DEPTH_BUFFER_BIT );

        gl.glLightfv(GL.GL_LIGHT0, GL.GL_POSITION, p.spot_position, 0);

        renderScene(gl);

        gl.glFlush();
}
public void renderScene(GL gl){
         for (int i=0; i<p.objs.size(); i++) {
            Obj obj = p.objs.elementAt(i);

            for (int j=0; j<obj.matNames.size(); j++){
                String matName = obj.matNames.elementAt(j);
                Material mat = p.nameMatHt.get(matName);
               
               
                    gl.glMaterialfv(GL.GL_FRONT, GL.GL_AMBIENT, mat.ambient, 0);
                    gl.glMaterialfv(GL.GL_FRONT, GL.GL_DIFFUSE, mat.diffuse, 0);
                    gl.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR, mat.specular,0);
                    gl.glMaterialf(GL.GL_FRONT, GL.GL_SHININESS, mat.shininess);
               
                IntBuffer indice = obj.indices.elementAt(j);
               
                if(mat.texFileName == null) {
                    gl.glDisable(GL.GL_TEXTURE_2D);
                    
                    gl.glBegin(GL.GL_TRIANGLES);
                    for (int k=0,l=0; k<indice.capacity(); k+=3,l++) {
                        int v1 = indice.get(k);
                        int v2 = indice.get(k+1);
                        int v3 = indice.get(k+2);
                        
//                        gl.glNormal3f(obj.planeNormsBuff.get(3*l),obj.planeNormsBuff.get(3*l + 1),obj.planeNormsBuff.get(3*l + 2));
                        gl.glNormal3f(obj.normsBuff.get(3*v1),obj.normsBuff.get(3*v1 + 1),obj.normsBuff.get(3*v1 + 2));
                        
                        gl.glVertex3f(obj.vertsBuff.get(3*v1),obj.vertsBuff.get(3*v1 + 1),obj.vertsBuff.get(3*v1 + 2));
                        
                        gl.glNormal3f(obj.normsBuff.get(3*v2),obj.normsBuff.get(3*v2 + 1),obj.normsBuff.get(3*v2 + 2));
                        
                        gl.glVertex3f(obj.vertsBuff.get(3*v2),obj.vertsBuff.get(3*v2 + 1),obj.vertsBuff.get(3*v2 + 2));
                        
                        gl.glNormal3f(obj.normsBuff.get(3*v3),obj.normsBuff.get(3*v3 + 1),obj.normsBuff.get(3*v3 + 2));
                        
                        gl.glVertex3f(obj.vertsBuff.get(3*v3),obj.vertsBuff.get(3*v3 + 1),obj.vertsBuff.get(3*v3 + 2));
                        
                    }
                    gl.glEnd();     
                }
                 else {
                    gl.glEnable(GL.GL_TEXTURE_2D);

                    try {
                        t = TextureIO.newTexture(new File("d:/images/"+mat.texFileName), false);
                        t.setTexParameteri(GL.GL_TEXTURE_MIN_FILTER, GL.GL_LINEAR);
                        t.setTexParameteri(GL.GL_TEXTURE_MAG_FILTER, GL.GL_LINEAR);
                        t.setTexParameteri(GL.GL_TEXTURE_WRAP_S, GL.GL_REPEAT);
                        t.setTexParameteri(GL.GL_TEXTURE_WRAP_T, GL.GL_REPEAT);
                        t.bind();
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    gl.glBegin(GL.GL_TRIANGLES);
                    for (int k=0, l=0; k<indice.capacity(); k+=3,l++) {
                        int v1 = indice.get(k);
                        int v2 = indice.get(k+1);
                        int v3 = indice.get(k+2);
                        
//                        gl.glNormal3f(obj.planeNormsBuff.get(3*l),obj.planeNormsBuff.get(3*l + 1),obj.planeNormsBuff.get(3*l + 2));

                        gl.glNormal3f(obj.normsBuff.get(3*v1),obj.normsBuff.get(3*v1 + 1),obj.normsBuff.get(3*v1 + 2));
                        
                        float tx1 = (obj.texsBuff.get(2*v1) - mat.ou - 0.5f)*mat.tu + 0.5f;
                        float ty1 = 1.5f - (obj.texsBuff.get(2*v1 + 1) - mat.ov - 0.5f)*mat.tv;
                        gl.glTexCoord2f(tx1, ty1);
                        
                        gl.glVertex3f(obj.vertsBuff.get(3*v1),obj.vertsBuff.get(3*v1 + 1),obj.vertsBuff.get(3*v1 + 2));
                        
                        gl.glNormal3f(obj.normsBuff.get(3*v2),obj.normsBuff.get(3*v2 + 1),obj.normsBuff.get(3*v2 + 2));
                        
                        float tx2 = (obj.texsBuff.get(2*v2) - mat.ou - 0.5f)*mat.tu + 0.5f;
                        float ty2 = 1.5f - (obj.texsBuff.get(2*v2 + 1) - mat.ov - 0.5f)*mat.tv;
                        gl.glTexCoord2f(tx2, ty2);
                        
                        gl.glVertex3f(obj.vertsBuff.get(3*v2),obj.vertsBuff.get(3*v2 + 1),obj.vertsBuff.get(3*v2 + 2));
                        
                        gl.glNormal3f(obj.normsBuff.get(3*v3),obj.normsBuff.get(3*v3 + 1),obj.normsBuff.get(3*v3 + 2));
                        
                        float tx3 = (obj.texsBuff.get(2*v3) - mat.ou - 0.5f)*mat.tu + 0.5f;
                        float ty3 = 1.5f - (obj.texsBuff.get(2*v3 + 1) - mat.ov - 0.5f)*mat.tv;
                        gl.glTexCoord2f(tx3, ty3);
                        
                        gl.glVertex3f(obj.vertsBuff.get(3*v3),obj.vertsBuff.get(3*v3 + 1),obj.vertsBuff.get(3*v3 + 2));
                        
                    }
                    gl.glEnd();        
                    
                }
             }
        }
    }



11

主题

1238

帖子

1782

积分

金牌会员

Rank: 6Rank: 6

积分
1782
发表于 2011-4-10 18:59:00 | 显示全部楼层

Re:求解:openGL加载3DS文件的问题

永远支持JAVA!!!支持Opengl!!!请放弃C++和DX吧!!!

28

主题

73

帖子

73

积分

注册会员

Rank: 2

积分
73
发表于 2011-4-11 20:37:00 | 显示全部楼层

Re:求解:openGL加载3DS文件的问题

支持C++和OpenGL,不喜欢JAVA

0

主题

3

帖子

0

积分

新手上路

Rank: 1

积分
0
发表于 2011-5-27 08:41:00 | 显示全部楼层

Re:求解:openGL加载3DS文件的问题

这个你可以参考lib3ds,同时模型的渲染还涉及到纹理文件格式解析,一个比较好的3DS解析是lib3DS, OSG就是用这个来解析,和渲染的。你首先确定是出错时在加载解析模型阶段,还是渲染阶段。
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

作品发布|文章投稿|广告合作|关于本站|游戏开发论坛 ( 闽ICP备17032699号-3 )

GMT+8, 2025-6-8 05:47

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表