这是最近在编写白膜发布工具代码中遇到如下的问题,总的来说,是对数据结构不够了解,以至于遇到各种各样的困难。
这几天在写到将数据添加到缓冲区时,总报出来重复添加多个数据对象的错误。依据相关的资料,估计是重复创建同样的缓冲。好了,于是对这个问题,改了发布数据的源代码。又遇到这样的问题,没有解析到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