Cesium开发&白膜发布工具开发中遇到的数据组织问题

这是最近在编写白膜发布工具代码中遇到如下的问题,总的来说,是对数据结构不够了解,以至于遇到各种各样的困难。

这几天在写到将数据添加到缓冲区时,总报出来重复添加多个数据对象的错误。依据相关的资料,估计是重复创建同样的缓冲。好了,于是对这个问题,改了发布数据的源代码。又遇到这样的问题,没有解析到buferView对象。

好了,我们来看一下报错位置的源代码。在下面的这个代码中,是创建顶点数据。Cesium中会遍历mesh,然后找到对应的primitive属性的一些值。接下来就是获取相关的属性信息了。

    ForEach.accessorContainingVertexAttributeData = function(gltf, handler) {
        var visited = {};
        return ForEach.mesh(gltf, function(mesh) {
            return ForEach.meshPrimitive(mesh, function(primitive) {
                var value = ForEach.meshPrimitiveAttribute(primitive, function(accessorId) {
                    if (!defined(visited[accessorId])) {
                        visited[accessorId] = true;
                        value = handler(accessorId);

                        if (defined(value)) {
                            return value;
                        }
                    }
                });

                if (defined(value)) {
                    return value;
                }

                return ForEach.meshPrimitiveTarget(primitive, function(target) {
                    return ForEach.meshPrimitiveTargetAttribute(target, function(accessorId) {
                        if (!defined(visited[accessorId])) {
                            visited[accessorId] = true;
                            value = handler(accessorId);

                            if (defined(value)) {
                                return value;
                            }
                        }
                    });
                });
            });
        });
    };

    ForEach.accessorContainingIndexData = function(gltf, handler) {
        var visited = {};
        return ForEach.mesh(gltf, function(mesh) {
            return ForEach.meshPrimitive(mesh, function(primitive) {
                var indices = primitive.indices;
                if (defined(indices) && !defined(visited[indices])) {
                    visited[indices] = true;
                    var value = handler(indices);

                    if (defined(value)) {
                        return value;
                    }
                }
            });
        });
    };

mesh依据其属性,去寻找访问器accessor。这里我们需要注意的是,有nomal,position等属性。

 

而现在我们来看一下访问器数据。每个访问器可以理解为对数据缓冲区的访问标记。标记隶属哪一个缓冲视图,这个非常重要。

在代码中,通过primitive相应的属性元素来寻找acessor,而我们这里出现的问题是acessor中越界了,而找不到访问器的元素。所以报了如上面的错误。因而我们需要在发布处理数据的工具中,设置好对应的acesess访问器正确位置。

visited[accessorId]

弄清楚上面的代码后,接着调试。虽然数据能够显示出来了,但是遇到下面的错误。大概意思是缓冲不能使用多个目标。

在这一部分中遇到的错误是。创建的缓冲区绑定使用了不同的目标对象,在cesium中,缓冲区要使用相同的绑定,创建顶点的代码在Model类中,在这里寻找到访问器。图元primitive按照属性去取出相应的访问器,访问器按照自己的缓冲区视图,相应的找到目标target,在这里设置一样的值,才能用于绑定缓冲对象。否则会报上面的错误。

   function createVertexArrays(model, context) {
        var loadResources = model._loadResources;
        if (!loadResources.finishedBuffersCreation() || !loadResources.finishedProgramCreation()
                || !loadResources.createVertexArrays) {
            return;
        }
        loadResources.createVertexArrays = false;

        var rendererBuffers = model._rendererResources.buffers;
        var type=typeof rendererBuffers
        for(var index=0;index<3;index++){
            var a=rendererBuffers[index];
            var b=rendererBuffers[index+1]

        }

        var rendererVertexArrays = model._rendererResources.vertexArrays;
        var gltf = model.gltf;
        var accessors = gltf.accessors;
        ForEach.mesh(gltf, function(mesh, meshId) {
            ForEach.meshPrimitive(mesh, function(primitive, primitiveId) {
                var attributes = [];
                var attributeLocation;
                var attributeLocations = getAttributeLocations(model, primitive);
                var decodedData = model._decodedData[meshId + '.primitive.' + primitiveId];
                ForEach.meshPrimitiveAttribute(primitive, function(accessorId, attributeName) {
                    // Skip if the attribute is not used by the material, e.g., because the asset
                    // was exported with an attribute that wasn't used and the asset wasn't optimized.
                    attributeLocation = attributeLocations[attributeName];
                    if (defined(attributeLocation)) {
                        // Use attributes of previously decoded draco geometry
                        if (defined(decodedData)) {
                            var decodedAttributes = decodedData.attributes;
                            if (decodedAttributes.hasOwnProperty(attributeName)) {
                                var decodedAttribute = decodedAttributes[attributeName];
                                attributes.push({
                                    index: attributeLocation,
                                    vertexBuffer: rendererBuffers[decodedAttribute.bufferView],
                                    componentsPerAttribute: decodedAttribute.componentsPerAttribute,
                                    componentDatatype: decodedAttribute.componentDatatype,
                                    normalize: decodedAttribute.normalized,
                                    offsetInBytes: decodedAttribute.byteOffset,
                                    strideInBytes: decodedAttribute.byteStride
                                });

                                return;
                            }
                        }

                        var a = accessors[accessorId];
                        if(a.bufferView==34963){

                            var mm=0;
                        }
                        var normalize = defined(a.normalized) && a.normalized;
                        attributes.push({
                            index: attributeLocation,
                            vertexBuffer: rendererBuffers[a.bufferView],
                            componentsPerAttribute: numberOfComponentsForType(a.type),
                            componentDatatype: a.componentType,
                            normalize: normalize,
                            offsetInBytes: a.byteOffset,
                            strideInBytes: getAccessorByteStride(gltf, a)
                        });
                    }
                });

                // Add pre-created attributes
                var attribute;
                var attributeName;
                var precreatedAttributes = model._precreatedAttributes;
                if (defined(precreatedAttributes)) {
                    for (attributeName in precreatedAttributes) {
                        if (precreatedAttributes.hasOwnProperty(attributeName)) {
                            attributeLocation = attributeLocations[attributeName];
                            if (defined(attributeLocation)) {
                                attribute = precreatedAttributes[attributeName];
                                attribute.index = attributeLocation;
                                attributes.push(attribute);
                            }
                        }
                    }
                }

                var indexBuffer;
                if (defined(primitive.indices)) {
                    var accessor = accessors[primitive.indices];
                    var bufferView = accessor.bufferView;

                    // Use buffer of previously decoded draco geometry
                    if (defined(decodedData)) {
                        bufferView = decodedData.bufferView;
                    }

                    indexBuffer = rendererBuffers[bufferView];
                }
                rendererVertexArrays[meshId + '.primitive.' + primitiveId] = new VertexArray({
                    context: context,
                    attributes: attributes,
                    indexBuffer: indexBuffer
                });
            });
        });
    }

解决上面的问题后,又遇到下面的警告。其实在这里遇到问题可以说是上面在组织数据,创建一个与顶点相同的bufferView目标(target)对象时设置的数据偏移不正确造成的,在这里我们需要在开发的切图工具中,将偏移值设置为0即可。

上面的警告,如下。

[.WebGL-0000029779691E10]GL ERROR :GL_INVALID_OPERATION : glDrawElements: attempt to access out of range vertices in attribute 2

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

yGIS

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值