zoukankan      html  css  js  c++  java
  • WebGL笔记(五):封装顶点和颜色等数组数据(一)

    顶点和颜色数据,均是数组类型,但数据冗长,例如一个立方体的颜色数据长度有96个,顶点为72个,管理比较麻烦。但是二者又有很大的相似性,不同之处仅在于分组的大小和取值范围。按照面向对象编程的思路,应该首先封装一个数组管理基类,然后通过继承和重载来分别实现顶点和颜色类。

    基于Javascript面向对象方面的特性,首先建立一个工厂类作为实现继承的工具:

    var Inherit = {
        /* 对对象进行浅表复制,主要用于重载(覆盖)某些方法或属性 */
        extend : function(o, oo){
            for(var p in oo){ o[p] = oo[p]; };
            p = null;
        },
        /*
        * 通过创建的基类实例建立原型链,实现继承
        * target:子类构造函数名
        * obj:基类实例
        * ext:扩展属性,包括子类独有的属性/方法和需要重载的部分
        */
        inherit : function(target, obj, ext){
            if(typeof target != 'function') return;
            target.prototype = obj;
            if(!!ext && ext instanceof Object){
                this.extend(target.prototype, ext);
            }
        }
    }

    然后建立一个数组管理基类ArrayHelper

    /*
    * ArrayHelper
    * 数组管理基类
    * by MK 2011-12-1
    */
    function ArrayHelper(){ }
    ArrayHelper.prototype = {
        IS_ArrayHelper : true,
        /* 分组单元长度,初始值为1,颜色应为4,定点应为3,需重载 */
        length : 1,
        /* 附加到原始数组
        @data:原始数组
        @offset:位于原始数组的偏移量
        */
        attach : function(data, offset){
            delete this.data;
            delete this.offset;
            if(data instanceof Array){
                this.data = data;
                this.offset = Math.max(offset || 0, 0);
            }
        },
        /* 遍历所位于的数组区域,并执行回调函数 */
        each : function(callback){
            if(typeof callback == 'function'){
                for(var i = 0; i < this.length; i++){
                    callback(this.data, i + this.offset, i);
                }
            }
        },
        /* 获取本区索引位置值,index为相对位置 */
        get : function(index){
            if(typeof index == 'number' && index < this.length){
                return this.data[index + this.offset];
            }
        },
        /* 设置本区索引位置值,index为相对位置。具体执行取决于参数状态。需重载 */
        set : function(value, index){
            if(typeof index == 'number' && index < this.length){
                this.data[index + this.offset] = value;
            } else if(value instanceof Array){
                this.each(function(data, ii, i){
                    if(i < value.length){
                        data[ii] = value[i];
                    }
                });
            } else if(value === 0 || !!value){
                this.each(function(data, ii){
                    data[ii] = value;
                });
            }
        },
        /* 本区数据归零 */
        clear : function(){
            this.each(function(data, ii){ data[ii] = 0; });
        },
        /* 返回本区数据的一个副本 */
        array : function(){
            return this.data.slice(this.offset, this.offset + this.length);
        }
    }

    下面使用Iherit对其进行继承重载,实现顶点与颜色两个区域管理类。

    首先是颜色类

    /*
    ColorHelper
    颜色管理类
    by MK 2011-12-2
    */
    var ColorHelper = function(data, offset){
        /* 尝试附加数据 */
        this.attach(data, offset);
        /* 重载本区长度值 */
        this.length = 4;
    }
    /* 扩展ColorHelper的静态方法 */
    Inherit.extend(ColorHelper, {
        /* 对象转换为颜色数据。转换失败则返回0 */
        ObjectToNumber : function(s, d){
            return (!!s?isNaN(s=Number('0x'+((s=s+'').length>1?s.substr(0,2):s+s)))?d||0:s:s===0?s:d||0)/255;
        },
        /*
        * 将CSS颜色标记转换为颜色数组 [R, G, B, A]。
        * 返回一个4个元素的数组,每个元素均在0~1之间
        * 仅接受字符串类型参数
        * 处理方法:
        * 1. #fff/#ffff,以#ffffff或#ffffffff方式解读
        * 2. #ffffff/#ffffffff,转换为三组或四组数据,顺序为R G B A。A部分失缺按ff处理
        * 3. 5字补齐为6字,7字补齐为8字
        * 4. 大于8字取前8字;小于3字,例如#cc,按#ccccccff处理
        * 5. 井号不必需,读取时会掠过。
        */
        FromCSS : function(v){
            if(typeof v != 'string' || !v.length) return null;
            if(v.charAt(0) == '#') v = v.substr(1);
            if(v.length < 3){
                return [v = this.ObjectToNumber(v), v, v, 1];
            }
            var reg;
            switch(v.length){
                case 3: case 4:
                    reg = /[0-f]/ig;
                    break;
                case 6: case 8:
                    reg = /[0-f]{2}/ig;
                    break;
                case 5: case 7:
                    return this.FromCSS(v + v.charAt(v.length - 1));
                default:
                    return this.FromCSS(v.substr(0, 8));
            }
            arr = []
            v.replace(reg,function(m){arr.push(ColorHelper.ObjectToNumber(m));});
            v = reg = null;
            return arr;
        },
        /* 返回一个0~1之间的数 */
        Fix : function(v){
            return typeof v != 'number' 
                ? this.ObjectToNumber(v) 
                : this.Range(v > 1 ? v / 255 : v, 0, 1); 
        },
        /* 返回指定范围的数 */
        Range : function(v, mi, ma){
            return Math.max(mi, Math.min(ma, v))
        }
    });
    /* ColorHelper 对 ArrayHelper 的继承与重载 */
    Inherit.inherit(ColorHelper, new ArrayHelper(), {
        /* 随机设置RGB三个值 */
        rand : function(){
            this.each(function(data, ii){
                data[ii] = Math.random();
            });
            this.set(1, 3);
        },
        /*
        * 重载set
        * 动态参数
        * 处理方式:
        * 1. 没有参数时,RGB归零,A=1
        * 2. 1个参数时,字符串类型则尝试转换为CSS颜色,数字类型则调用基类set方法赋值
        * 3. 2个或更多参数时,调用基类set方法赋值
        */
        set : function(){
            var args = Array.prototype.slice.call(arguments, 0)
                , _set = ArrayHelper.prototype.set;
                ;
            switch(args.length){
                case 0:
                    this.clear();
                    _set.apply(this, [1, 3]);
                    break;
                case 1:
                    if(typeof args[0] == 'string' && args[0].length){
                        _set.call(this, ColorHelper.FromCSS(args[0]));
                    } else if(typeof args[0] == 'number'){
                        _set.call(this, ColorHelper.Fix(args[0]));
                    }
                    break;
                case 2:
                    args[0] = ColorHelper.Fix(args[0]); 
                    args[1] = typeof args[1] == 'number' ? ColorHelper.Range(args[1], 0, 3) : 0;
                    _set.apply(this, args);
                    break;
                default:
                    var i = 0, len = args.length;
                    for(; i < len; i++){
                        args[i] = ColorHelper.Fix(args[i]); 
                    }
                    _set.call(this, args);
                    break;
            }
            args = _set = null;
        }
    });

    顶点类比较简单

    /*
    * VerticesHelper
    * 顶点管理类
    * by MK 2011-12-2
    */
    function VerticesHelper(data, offset){
        this.attach(data, offset);
        this.length = 3;
    }
    /* VerticesHelper 对 ArrayHelper 继承和重载 */
    Inherit.inherit(VerticesHelper, new ArrayHelper(), {
        /*
        * 将本区每个值增长一个值,实现顶点的移动
        * index有效时,对指定索引处赋值
        * index无效时,对本区全体赋值
        */
        move : function(v, index){
            if(typeof v != 'number' && (!v || isNaN(v = parseFloat(v)))){
                v = 0;
            }
            if(typeof index == 'number'){
                this.set(this.get(index) * v, index);
            } else {
                this.each(function(data, ii, i){
                    data[ii] += v;
                });
            }
        }
    });

    今天先写到这里。关于继承和重载方面欢迎大家多提意见。今天周末,祝大家周末愉快,我得回家了。

    下一篇将介绍一个GroupHelper和ArrayHelper结合管理整个数组的应用,并扩展VerticesGroup和ColorGroup。代码文件先不上传了,有些地方还要完善一下,至少注释还没写完整哈!

  • 相关阅读:
    Free Energies: MMPBSA
    蛋白添加ACE,NME
    生物信息学在线软件集锦
    Developing Nonstandard Parameters:MCPB.py Example
    python锁定焦点到指定进程窗口的参考方法
    【Windows程序设计】Unicode简介
    SecureCRT连接linux终端中文显示乱码解决办法
    ubuntu下音箱有声音,耳机没声音之类问题解决办法
    python处理不同编码格式的文件
    【Windows程序设计】第一个Windows程序
  • 原文地址:https://www.cnblogs.com/muse/p/2272498.html
Copyright © 2011-2022 走看看