复杂表面实现动态材质

利用polygonGraphic,可以在一个多边形上实现动态材质,方法是将其material属性赋值为videoElement,并实现时钟同步

 var videoElement=document.getElementById("videoTest");
           new Cesium.VideoSynchronizer({
               clock:viewer.clock,
               element:videoElement
           });
           viewer.clock.shouldAnimate=true;
为了简单,以rectangleGraphic为例,polygonGraphic相似
    var entity=viewer.entities.add({
                  rectangle : {
                    coordinates : Cesium.Rectangle.fromDegrees(116, 39,117,40),
                    height:10,
                    extrudedHeight:10.5,
                    material:videoElement,
         
                },
但如果所绘几何体比polygonGraphic还要复杂,如何在其上实现动态材质呢?有两个思路:①将复杂几何体构造为gltf,通过修改model.js里createTexture的调用以实现材质动态化。②利用entity的动态材质原理,修改其构造几何体的代码部分以实现。下面以第二个思路为例实现之,标红的为修改代码。
 
零、最后的代码大概如:
    var entity=viewer.entities.add({
                  rectangle : {
                    coordinates : Cesium.Rectangle.fromDegrees(116, 39,117,40),
                    height:10,
                    material:videoElement,
                   geoUrl:"http://localhost:8080/data/attributes.json"
                }
  其中geoUrl为几何体的几何信息,格式大概为:

{
"positions":[-2177751.988653067,4388739.21593798,4070072.117434415,-2177755.8383054473,4388737.305686096,4070072.117434416,-2177753.1226620823,4388741.501262417,4070069.0669684587,-2177756.972316467,4388739.591009537,4070069.0669684587,-2177751.818168628,4388738.8723672945,4070071.796663094,-2177755.6678207065,4388736.962115559,4070071.796663095,-2177752.952177555,4388741.157691553,4070068.746197378,-2177756.801831638,4388739.247438823,4070068.746197378,-2177751.988653067,4388739.21593798,4070072.117434415,-2177751.818168628,4388738.8723672945,4070071.796663094,-2177753.1226620823,4388741.501262417,4070069.0669684587,-2177752.952177555,4388741.157691553,4070068.746197378,-2177753.1226620823,4388741.501262417,4070069.0669684587,-2177752.952177555,4388741.157691553,4070068.746197378,-2177756.972316467,4388739.591009537,4070069.0669684587,-2177756.801831638,4388739.247438823,4070068.746197378,-2177756.972316467,4388739.591009537,4070069.0669684587,-2177756.801831638,4388739.247438823,4070068.746197378,-2177755.8383054473,4388737.305686096,4070072.117434416,-2177755.6678207065,4388736.962115559,4070071.796663095,-2177755.8383054473,4388737.305686096,4070072.117434416,-2177755.6678207065,4388736.962115559,4070071.796663095,-2177751.988653067,4388739.21593798,4070072.117434415,-2177751.818168628,4388738.8723672945,4070071.796663094],
"normals":[-0.34096887707710266,0.6871413588523865,0.6415426135063171,-0.3409694731235504,0.6871410608291626,0.6415426135063171,-0.340969055891037,0.6871417164802551,0.6415421366691589,-0.34096965193748474,0.6871414184570312,0.6415421366691589,0.34096887707710266,-0.6871413588523865,-0.6415426135063171,0.3409694731235504,-0.6871410608291626,-0.6415426135063171,0.340969055891037,-0.6871417164802551,-0.6415421366691589,0.34096965193748474,-0.6871414184570312,-0.6415421366691589,0.8957797884941101,0.44449809193611145,-3.6706260253538403e-10,0.8957797884941101,0.44449809193611145,-3.6706260253538403e-10,0.8957797884941101,0.44449809193611145,-3.6706260253538403e-10,0.8957797884941101,0.44449809193611145,-3.6706260253538403e-10,-0.2851645350456238,0.5746803879737854,-0.7670877575874329,-0.2851645350456238,0.5746803879737854,-0.7670877575874329,-0.2851645350456238,0.5746803879737854,-0.7670877575874329,-0.2851645350456238,0.5746803879737854,-0.7670877575874329,-0.8957794308662415,-0.4444988965988159,-4.509475570735333e-10,-0.8957794308662415,-0.4444988965988159,-4.509475570735333e-10,-0.8957794308662415,-0.4444988965988159,-4.509475570735333e-10,-0.8957794308662415,-0.4444988965988159,-4.509475570735333e-10,0.2851647436618805,-0.5746808052062988,0.7670873999595642,0.2851647436618805,-0.5746808052062988,0.7670873999595642,0.2851647436618805,-0.5746808052062988,0.7670873999595642,0.2851647436618805,-0.5746808052062988,0.7670873999595642],
"sts":[0,1,1,1,0,0,1,0,0,1,1,1,0,0,1,0,0,1,0,1,0,0,0,0,0,0,0,0,1,0,1,0,1,0,1,0,1,1,1,1,1,1,1,1,0,1,0,1],
"indices":[0,2,1,1,2,3,5,6,4,7,6,5,8,9,10,10,9,11,12,13,14,14,13,15,16,17,18,18,17,19,20,21,22,22,21,23],
"boundingSphere":{
"center":{"x": -2177754.3952418366, "y": 4388739.231689012, "z": 4070070.4318156964},
"radius":3.177581298845232
}
}

coordinates 和height属性值随意,因为最后的几何体数据来自json文件,之所以给height赋值,是因为如果height和extrudedHeight若同时不参与定义,则cesium将最终构造groundPrimitive以实现贴地。
一、修改entity.js文件,在构造函数中增加以下代码:
function Entity(options){
...
   if(defined(options.rectangle)){
            this.geoUrl=options.rectangle.geoUrl;
        }
}
其中,options为零中add的参数,结果是将json路径保存到entity的geoUrl属性
二、修改primitive.js的loadAsynchronous函数
function loadAsynchronous(primitive, frameState) {
  。。。
  if (primitive._state === PrimitiveState.READY) {
    。。。
    
  if (primitive._state === PrimitiveState.READY) {
            instances = (isArray(primitive.geometryInstances)) ? primitive.geometryInstances :                          [primitive.geometryInstances];
            var length = primitive._numberOfInstances = instances.length;

            var promises = [];
            var subTasks = [];
            for (i = 0; i < length; ++i) {
                geometry = instances[i].geometry;
                instanceIds.push(instances[i].id);

                if (!defined(geometry._workerName)) {
                    throw new DeveloperError('_workerName must be defined for asynchronous geometry.');
                }
                //>>includeEnd('debug');

                subTasks.push({
                    moduleName : geometry._workerName,
                    geometry : geometry,
               
                    geoUrl:instances[i].id.geoUrl,
                   
                });
            }
  }
},
以上代码,将geoUrl传给subTask,
三、修改createGeometry.js的createGeometry函数
 function createGeometry(parameters, transferableObjects) {
        var subTasks = parameters.subTasks;
        var length = subTasks.length;
        var resultsOrPromises = new Array(length);

        for (var i = 0; i < length; i++) {
            var task = subTasks[i];
            var geometry = task.geometry;
            var moduleName = task.moduleName;

            if (defined(moduleName)) {
                var createFunction = getModule(moduleName);
                //wjwChange
                if(moduleName==='createRectangleGeometry')
                    resultsOrPromises[i] = createFunction(geometry, task.offset,task.geoUrl);
                else
                    resultsOrPromises[i] = createFunction(geometry, task.offset);
            } else {
                //Already created geometry
                resultsOrPromises[i] = geometry;
            }
        }

        return when.all(resultsOrPromises, function(results) {
            return PrimitivePipeline.packCreateGeometryResults(results, transferableObjects);
        });
    }

    return createTaskProcessorWorker(createGeometry);
});
四、修改createRectangleGeometry.js的createRectangleGeometry函数,增加geoUrl参数
    //wjwChange
    function createRectangleGeometry(rectangleGeometry, offset,geoUrl) {
        if (defined(offset)) {
            rectangleGeometry = RectangleGeometry.unpack(rectangleGeometry, offset);
        }
        rectangleGeometry._ellipsoid = Ellipsoid.clone(rectangleGeometry._ellipsoid);
        rectangleGeometry._rectangle = Rectangle.clone(rectangleGeometry._rectangle);
        return RectangleGeometry.createGeometry(rectangleGeometry,geoUrl);
    }
五、修改RectangleGeometry.createGeometry函数,
 RectangleGeometry.createGeometry = function(rectangleGeometry,geoUrl) {
        if(!defined(geoUrl)){
    。。。
  }
  else
  {
    
     var promise=getAtrributes(geoUrl);
             return promise;
  }
},
其中getAtrributes为直接读取坐标json的函数:
function getAtrributes(dataUrl){
        var attributes={};
        var defer=when.defer();
        fetch(dataUrl).then(res=>res.json()).then(result=>{
           attributes.positions= Float64Array.from(result.positions);
           attributes.normals=Float32Array.from(result.normals);
           attributes.sts=Float32Array.from(result.sts)
           attributes.indices=Uint16Array.from(result.indices);


        var geo = new Geometry({
            attributes : new GeometryAttributes(),
            primitiveType : PrimitiveType.TRIANGLES
        });

        geo.attributes.position = new GeometryAttribute({
            componentDatatype : ComponentDatatype.DOUBLE,
            componentsPerAttribute : 3,
            values : attributes.positions
        });
       
        geo.attributes.normal = new GeometryAttribute({
            componentDatatype : ComponentDatatype.FLOAT,
            componentsPerAttribute : 3,
            values : attributes.normals
        });

        geo.attributes.st = new GeometryAttribute({
            componentDatatype : ComponentDatatype.FLOAT,
            componentsPerAttribute : 2,
            values : attributes.sts
        });
       
        geo.indices=attributes.indices;

        geo.primitiveType = 4;
        var center=result.boundingSphere.center;
        geo.boundingSphere=new BoundingSphere(new Cartesian3(center.x,center.y,center.z),
            result.boundingSphere.radius);
        defer.resolve(geo);
 

        })

        return defer.promise;
    }
这样,可以用三维建模软件编辑三维几何体,并匹配视频的一帧,输出几何体信息为上述json格式,即可实现复杂几何体的材质动态化。
posted @ 2022-06-06 17:44  jwwry  阅读(184)  评论(0编辑  收藏  举报