`
xhuixuanwen
  • 浏览: 6364 次
  • 性别: Icon_minigender_1
  • 来自: 上海
最近访客 更多访客>>
文章分类
社区版块
存档分类
最新评论

3D模板阴影原理

阅读更多
1:先从3dsMax中导出一个简单的场景,一个园环,球,平面。

2:园环直接面向光源,园环对球体来说是一个光线的阻挡物,园环在它上面形成阴影,同时,园环和球体对平面来说是光线的阻挡物,所以,同时在其上面形成阴影。

3: 要产生模板阴影,先要找出在园环和球体上面面向光线的面,去除背向光线的面,通过测试光线同园环和球体上面每一个所组成的小角形的法线的夹角是否小于90度,即光线矢量同法线矢量的点积要大于零。

4:在余下的所有面向光线的面中,把每个面的每条边可以保存到一个Vector中,不过在保存之前,先把该条边同已保存在Vector中的每条边先进行逐一比较,如果,找到的这条边同它的两个顶点相同,但顺序相反,则取走在Vector中的这条边。
如找不到,则把该条边加入到Vector中,最后将得到一条(或两条)轮廓线(见图红色线)。

5: 把轮廓线上的每个点延着光线方向延长一定的长度(见黄线),黄线所构成的面(所谓的阴影体)同场景去作比较,即模板测试(stencil)
最后画出阴影部分和非阴影部分,这就是基本的原理。






import com.sun.opengl.util.texture.Texture;
import com.sun.opengl.util.texture.TextureIO;
import java.io.File;
import java.nio.IntBuffer;
import java.util.Vector;
import javax.media.opengl.GL;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLJPanel;
import javax.media.opengl.glu.GLU;

public class Main extends javax.swing.JFrame implements GLEventListener{
    private ThreeDSParser p;
    Texture t;
    int[] shadowVolume = new int[2];
    int index = 0;
    float ext = 2.2f;

    public void init(GLAutoDrawable drawable){
        p = new ThreeDSParser();
        p.parseFile("D:/3dsfiles/simpleScene.3DS");
        
        
        GL gl = drawable.getGL();

        gl.glLightfv(GL.GL_LIGHT0, GL.GL_AMBIENT, new float[]{0.0f, .0f, 0f, 1.0f}, 0);
        gl.glLightfv(GL.GL_LIGHT0, GL.GL_DIFFUSE, new float[]{1.0f, 1.0f, 1.0f, 1.0f}, 0);
        gl.glLightfv(GL.GL_LIGHT0, GL.GL_SPECULAR, new float[]{1.0f, 1.0f, 1.0f, 1.0f}, 0);
        gl.glLightf(GL.GL_LIGHT0, GL.GL_SHININESS, 60f);

        gl.glLightModelfv(GL.GL_LIGHT_MODEL_AMBIENT, new float[]{.05f, .05f, .05f, 1.0f}, 0);
        gl.glLightModeli(GL.GL_LIGHT_MODEL_COLOR_CONTROL,GL.GL_SEPARATE_SPECULAR_COLOR);
        
        gl.glEnable(GL.GL_LIGHTING);
        gl.glEnable(GL.GL_LIGHT0);

        gl.glEnable(GL.GL_DEPTH_TEST);
        gl.glDepthFunc(GL.GL_LESS);
        gl.glEnable(GL.GL_NORMALIZE);
        gl.glShadeModel(GL.GL_SMOOTH);
        
        gl.glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
        
        computeSilhouette(gl,0);
        computeSilhouette(gl,2);
     }

     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.GL_STENCIL_BUFFER_BIT );

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

        
        //不写了颜色缓存,写了深度缓存,仅用作深度比较
        gl.glColorMask( false, false, false, false );
        renderScene(gl,0);   
     
        //模板测试时,不改变深度缓存
        gl.glEnable( GL.GL_CULL_FACE );
        gl.glEnable( GL.GL_STENCIL_TEST );
        gl.glDepthMask( false );
        gl.glStencilFunc( GL.GL_ALWAYS, 0, 0xffff );
        
        /*去除阴影体的背面,保留前面同整个场景进行模板测试
          *当过深度测试通过时,值加一GL.GL_INCR;否则不变GL.GL_KEEP
         */
        gl.glCullFace( GL.GL_BACK );
        gl.glStencilOp( GL.GL_KEEP, GL.GL_KEEP, GL.GL_INCR );
        for(int i=0; i<shadowVolume.length; i++){
            gl.glCallList(shadowVolume[i]);
        }
        
        /*去除阴影体的前面,保留背面同整个场景进行模板测试
          *当过深度测试通过时,值减一GL.GL_DECR;否则不变GL.GL_KEEP
         */
        gl.glCullFace( GL.GL_FRONT );
        gl.glStencilOp( GL.GL_KEEP, GL.GL_KEEP, GL.GL_DECR );
        for(int i=0; i<shadowVolume.length; i++){
            gl.glCallList(shadowVolume[i]);
        }

        //恢复可写了颜色和深度缓存
        gl.glDepthMask( true );
        gl.glDepthFunc( GL.GL_LEQUAL );
        gl.glColorMask( true, true, true, true );
        gl.glStencilOp( GL.GL_KEEP, GL.GL_KEEP, GL.GL_KEEP );
        gl.glCullFace( GL.GL_BACK );
        gl.glDisable( GL.GL_CULL_FACE );

        //在模板缓存值不等于参考值零处,画阴影部分
        gl.glStencilFunc( GL.GL_NOTEQUAL, 0, 0xffff );
        renderScene(gl,1);   

        //在模板缓存值等于参考值零处,画非阴影部分
        gl.glStencilFunc( GL.GL_EQUAL, 0, 0xffff );
        renderScene(gl,0);
        
        gl.glDepthFunc( GL.GL_LESS );
        gl.glDisable( GL.GL_STENCIL_TEST);

        
        gl.glFlush();
    }

    public void renderScene(GL gl,float a){
         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);
                
                if(a == 0){
                    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);
                }
                else {
                    gl.glMaterialfv(GL.GL_FRONT, GL.GL_SPECULAR, new float[]{0.0f, 0.0f,0.0f, 0.95f}, 0);
                    gl.glMaterialfv(GL.GL_FRONT, GL.GL_DIFFUSE, new float[]{0.05f, 0.05f,0.05f, 1f}, 0);
                }
                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.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.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();        
                    
                }
             }
        }
    }

    public void computeSilhouette(GL gl, int objIndex){
        
        Vector<Float> edges = new Vector<Float>();
        
        //光线的方向
        float[] lightDir = new float[3];
        lightDir[0] = p.spot_position[0];
        lightDir[1] = p.spot_position[1];
        lightDir[2] = p.spot_position[2];

        //导出模型全部顶点的索引
        Obj obj = p.objs.elementAt(objIndex);
        IntBuffer indices = obj.indices.elementAt(0);
        for (int k=0,l=0; k<indices.capacity(); k+=3,l++) {
            
            //取得每个三角形面的平面法线
            float a = obj.planeNormsBuff.get(3*l);
            float b = obj.planeNormsBuff.get(3*l + 1);
            float c = obj.planeNormsBuff.get(3*l + 2);
            
            //求得光线同法线的点积(夹角)
            float ldotn = a*lightDir[0] + b*lightDir[1] + c*lightDir[2];
            
            //通过判断点积来确定该面是否面向光源,背向光源去除。
            if (ldotn<0) continue;
            
            //分别取得三角形面的三条边
            for (int i=0; i<3; i++){
                int ev1 = indices.get(k+i);
                int ev2 = i == 2 ? indices.get(k): indices.get(k+i+1);

                //第一个顶点
                float x1 = obj.vertsBuff.get(3*ev1);
                float y1 = obj.vertsBuff.get(3*ev1 + 1);
                float z1 = obj.vertsBuff.get(3*ev1 + 2);
                //第二个顶点
                float x2 = obj.vertsBuff.get(3*ev2);
                float y2 = obj.vertsBuff.get(3*ev2 + 1);
                float z2 = obj.vertsBuff.get(3*ev2 + 2);
                
                //在edges Vector中寻找是否有顶点相同,但顺序相反的边。
                int j=0;
                for (; j<edges.size(); j+=6){
                    if (x1 == edges.elementAt(j+3) 
                            && y1 == edges.elementAt(j+4) 
                            && z1 == edges.elementAt(j+5)
                            && x2 == edges.elementAt(j)
                            && y2 == edges.elementAt(j+1)
                            && z2 == edges.elementAt(j+2)){
                        break;
                    }
                }
                
                if (edges.isEmpty() || j == edges.size()) {
                    //没的找到,则放入该条边
                    edges.addElement(x1);
                    edges.addElement(y1);
                    edges.addElement(z1);
                    edges.addElement(x2);
                    edges.addElement(y2);
                    edges.addElement(z2);
                } else {
                    //若找到,则取走Vector中顶点相同,但顺序相反的边
                    for (int h = 0; h<6; h++)
                        edges.removeElementAt(j);
                }

            }
        }

        //最终 edges Vector中是轮廓线的所有顶点
        
           
        shadowVolume[index] = gl.glGenLists(1);
        gl.glNewList(shadowVolume[index], GL.GL_COMPILE);
        {
            
            gl.glBegin( GL.GL_QUADS );
            gl.glLineWidth(1f);
            {
                gl.glColor3f( 0.5f, 0.5f, 0.1f );
  
                for (int i=0; i<edges.size(); i+=6) {
                    float x1 = edges.elementAt(i);
                    float y1 = edges.elementAt(i+1);
                    float z1 = edges.elementAt(i+2);
                    float x2 = edges.elementAt(i+3);
                    float y2 = edges.elementAt(i+4);
                    float z2 = edges.elementAt(i+5);
                    
                    gl.glVertex3f(x1, y1, z1);
                    
                    //把点延着光线方向延长一定的长度
                    float[] vExtended1 = extendVertex(x1, y1, z1, ext);
                    gl.glVertex3f( vExtended1[0], vExtended1[1], vExtended1[2] );
                    
                    float[] vExtended2 = extendVertex(x2, y2, z2, ext);
                    gl.glVertex3f( vExtended2[0], vExtended2[1], vExtended2[2] );
                    
                    gl.glVertex3f(x2, y2, z2);
                }
            }
            gl.glEnd();
            
        }
        gl.glEndList();
        
        index ++;
    }

    public float[] extendVertex( float x, float y, float z, float ext )
    {
        float[] lightDir = new float[3];

        lightDir[0] = x - p.spot_position[0];
        lightDir[1] = y - p.spot_position[1];
        lightDir[2] = z - p.spot_position[2];

        float[] newVert = new float[3];
        newVert[0] = p.spot_position[0] + lightDir[0] * ext;
        newVert[1] = p.spot_position[1] + lightDir[1] * ext;
        newVert[2] = p.spot_position[2] + lightDir[2] * ext;
        
        return newVert;
    }

    public void displayChanged(GLAutoDrawable gl, boolean modeChanged, boolean deviceChanged){ } 
}

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[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;
                    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]);
  
    }
    
    
}




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 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;
}




  • 大小: 165.7 KB
  • 大小: 166.4 KB
  • 大小: 172.4 KB
分享到:
评论

相关推荐

    3D阴影效果PPT图表下载

    首先,3D阴影效果在PPT中的应用涉及到图形设计的基本原理,如深度感知和空间关系。通过添加适当的阴影,可以模拟物体在三维空间中的位置和光照效果,使平面的图表显得有层次感,增加了视觉上的真实感。这种效果在...

    Direct3D原理与API参考(part2)

    本部分将深入探讨Direct3D的基本原理和API,帮助开发者理解和掌握其核心概念和技术。 1. **Direct3D版本与架构** - Direct3D有不同的版本,如Direct3D 9、10、11、12等,每个版本都带来了性能提升和新功能。Direct...

    Unity3D Shader系列之模板测试源码

    本系列文章聚焦于Unity3D Shader的高级技术,特别是模板(Stencil)测试,这是实现复杂图形效果的一种强大工具。模板测试允许我们对渲染像素进行额外的控制,根据预定义的模板条件来决定是否绘制该像素,从而实现如...

    CSS3带阴影的3D进度条插件

    "CSS3带阴影的3D进度条插件"就是利用CSS3特性来创建的一种创新的、具有立体感和阴影效果的进度条组件。这种插件可以提升网页的交互性和美观度,吸引用户注意力,从而提高用户对网站的满意度。 首先,我们需要了解...

    3D地产结构设计PPT模板下载

    2. **结构分析**:模板可能会涵盖结构力学的基本原理,如荷载计算、稳定性分析,以及如何通过3D模型进行结构性能评估。 3. **材料与施工工艺**:模板可能包含各种建筑材料的介绍,如混凝土、钢结构等,以及相应的...

    微信静态模板---图片3D立体切换

    首先,我们要理解3D立体切换的基本原理。在Web开发中,CSS3的transform属性是实现3D转换的关键。它可以改变元素的位置、大小和形状,包括translate()、rotate()、scale()等方法。当应用于图片时,rotateY()或rotateX...

    Fly3D 2.0 3D引擎源码及文档

    通过分析源码,开发者可以深入了解3D图形学原理,理解如何实现复杂的3D算法,例如: 1. **渲染管线**:研究DirectX或OpenGL的渲染流程,了解顶点着色器、几何着色器和像素着色器的工作方式。 2. **矩阵运算**:学习...

    OpenGL模板缓冲区应用示例源代码

    模板缓冲区的工作原理是通过设置一系列的模板测试规则,这些规则定义了像素如何与缓冲区中的模板值进行比较。当一个新的像素被渲染时,OpenGL会首先执行模板测试。如果测试通过,像素会被绘制;如果失败,像素则会被...

    3D球形标签云.rar

    在学习过程中,需要注意理解HTML结构、CSS3的3D转换以及JavaScript中的3D动画原理。通过实践和调试,可以逐步掌握这一先进技术,并将其应用于自己的项目中。 总的来说,3D球形标签云是一个结合了HTML、CSS和...

    3D-Dash.zip

    通过研究Dash-master文件中的源代码和资源,开发者可以深入理解3D游戏引擎的工作原理,提升自己的技术能力。无论你是初学者还是经验丰富的开发者,3D-Dash.zip都提供了无尽的可能性,等待你去探索和创新。

    direct 3d 技术内幕

    Direct3D技术内幕是深入理解这一核心技术的关键,它涵盖了Direct3D的工作原理、编程方法以及优化策略。在本书中,读者可以期待学习到关于3D图形编程的诸多方面。 首先,Direct3D的核心概念包括设备创建、上下文管理...

    3D游戏编程<<3DGame>>

    此外,光照和阴影是3D环境中不可或缺的部分,书籍会介绍各种光照模型,如环境光、点光源、平行光,以及阴影映射等技术,以增加场景的真实感。 渲染技术也是3D游戏编程的重点。书中会涉及像素着色器和顶点着色器的...

    3D字体动画

    在IT领域,3D字体动画是一种将文字转化为三维立体效果,并赋予动态...不过,为了更深入地理解和掌握3D字体动画的制作,建议学习基本的3D建模和动画原理,这样在实际操作中能更好地发挥创意,打造出独一无二的视觉作品。

    3D文字制作软件

    软件通常提供了丰富的预设模板,用户可以直接应用,也可以自定义调整,如修改文字的形状、大小、角度、深度,以及添加阴影、反射、透明度等效果,以达到理想中的视觉表现。 其次,3D文字软件往往具备动画功能,让...

    3D旋转球,可调节各项参数

    综上所述,这个项目涵盖了3D图形编程的基本原理,包括3D坐标系统、旋转矩阵、视图变换、光照模型,以及C#编程和WPF框架的应用。通过学习和实践这个项目,你可以提升对3D设计和编程的理解,并掌握创建互动3D模型的...

    Android 3D游戏开发技术宝典-OpenGL ES 2.0 (吴亚峰) 源代码

    12.3 模板测试 337 12.3.1 基本原理 337 12.3.2 一个简单的案例 340 12.4 任意剪裁平面 341 12.4.1 基本原理 341 12.4.2 茶壶被任意平面剪裁的案例 342 12.5 本章小结 344 第13章 顶点着色器...

    Direct3D教程

    1. **Direct3D基础**:首先,你需要了解Direct3D的基本架构和工作原理,包括设备创建、上下文管理、交换链设置等。这些基础知识构成了Direct3D编程的基础。 2. **渲染管线**:Direct3D的渲染管线是其核心工作流程,...

    精通direct3d图形及动画程序设计源代码源码

    本资料包“精通Direct3D图形及动画程序设计源代码”提供了丰富的源码示例,旨在帮助开发者深入理解Direct3D的工作原理,并能运用到实际项目中。 首先,你需要了解Direct3D的基础概念。Direct3D的核心是设备(Device...

    3D图像显示(源码、示例、说明文档)

    6. **范文/模板/素材**:在进行3D项目开发时,使用现有的模板或素材可以加快开发进程。Helix Toolkit可能提供了现成的3D模型、场景布局等,开发者可以在此基础上进行修改和扩展,快速搭建起自己的3D应用。 总之,...

    VC中在界面如何实现3D文字

    在VC++(Visual C++)开发环境中,创建具有3D效果的...总之,在VC++中实现3D文字是一项结合图形编程和Windows消息处理的任务,通过理解GDI的基本绘图原理,我们可以自由地在界面上创建出具有视觉吸引力的3D文字效果。

Global site tag (gtag.js) - Google Analytics