CesiumGS / cesium

An open-source JavaScript library for world-class 3D globes and maps :earth_americas:
https://cesium.com/cesiumjs/
Apache License 2.0
12.94k stars 3.49k forks source link

When I picked up a 3Dtile, an error occurred #11990

Closed HKEFU closed 5 months ago

HKEFU commented 5 months ago

What happened?

[Cesium WebGL] Vertex shader compile log: ERROR: 0:72: 'selectedFeature' : undeclared identifier ERROR: 0:72: 'id' : field selection requires structure, vector, or interface block on left hand side ERROR: 0:72: '<' : wrong operand types - no operation '<' exists that takes a left-hand operand of type 'const highp float' and a right operand of type 'highp int' (or there is no acceptable conversion) ERROR: 0:72: 'model_pickTexture' : undeclared identifier ERROR: 0:72: 'selectedFeature' : undeclared identifier ERROR: 0:72: 'st' : field selection requires structure, vector, or interface block on left hand side ERROR: 0:72: 'texture' : no matching overloaded function found ERROR: 0:72: '?:' : mismatching ternary operator operand types 'const mediump float and 'const 4-component vector of float'

Reproduction steps

1. 2. 3. ...

Sandcastle example

No response

Environment

[Cesium WebGL] Vertex shader source:

version 300 es

define HAS_ATMOSPHERE

define COMPUTE_POSITION_WC_ATMOSPHERE

define HAS_NORMALS

define HAS_TEXCOORD_0

define HAS_FEATURE_ID_0

define HAS_SELECTED_FEATURE_ID

define SELECTED_FEATURE_ID featureId_0

define HAS_SELECTED_FEATURE_ID_ATTRIBUTE

define USE_CPU_STYLING

define LOG_DEPTH

define OES_texture_float_linear

define OES_texture_float

line 0

const float czm_infinity = 5906376272000.0;

struct czm_ray { vec3 origin; vec3 direction; };

struct czm_raySegment { float start; float stop; };

const czm_raySegment czm_emptyRaySegment = czm_raySegment(-czm_infinity, -czm_infinity);

const czm_raySegment czm_fullRaySegment = czm_raySegment(0.0, czm_infinity);

uniform vec3 czm_atmosphereRayleighCoefficient; uniform vec3 czm_atmosphereMieCoefficient; uniform float czm_atmosphereMieScaleHeight; uniform float czm_atmosphereRayleighScaleHeight;

float czm_approximateTanh(float x) { float x2 = x x; return max(-1.0, min(1.0, x (27.0 + x2) / (27.0 + 9.0 * x2))); }

czm_raySegment czm_raySphereIntersectionInterval(czm_ray ray, vec3 center, float radius) { vec3 o = ray.origin; vec3 d = ray.direction;

vec3 oc = o - center;

float a = dot(d, d);
float b = 2.0 * dot(d, oc);
float c = dot(oc, oc) - (radius * radius);

float det = (b * b) - (4.0 * a * c);

if (det < 0.0) {
    return czm_emptyRaySegment;
}

float sqrtDet = sqrt(det);

float t0 = (-b - sqrtDet) / (2.0 * a);
float t1 = (-b + sqrtDet) / (2.0 * a);

czm_raySegment result = czm_raySegment(t0, t1);
return result;

}

uniform vec2 czm_currentFrustum; uniform mat4 czm_inverseProjection;

void czm_computeScattering( czm_ray primaryRay, float primaryRayLength, vec3 lightDirection, float atmosphereInnerRadius, out vec3 rayleighColor, out vec3 mieColor, out float opacity ) { const float ATMOSPHERE_THICKNESS = 111e3; const int PRIMARY_STEPS_MAX = 16; const int LIGHT_STEPS_MAX = 4;

rayleighColor = vec3(0.0);
mieColor = vec3(0.0);
opacity = 0.0;

float atmosphereOuterRadius = atmosphereInnerRadius + ATMOSPHERE_THICKNESS;

vec3 origin = vec3(0.0);

czm_raySegment primaryRayAtmosphereIntersect = czm_raySphereIntersectionInterval(primaryRay, origin, atmosphereOuterRadius);

if (primaryRayAtmosphereIntersect == czm_emptyRaySegment) {
    rayleighColor = vec3(1.0, 0.0, 1.0);
    return;
}

float x = 1e-7 * primaryRayAtmosphereIntersect.stop / length(primaryRayLength);

float w_stop_gt_lprl = 0.5 * (1.0 + czm_approximateTanh(x));

float start_0 = primaryRayAtmosphereIntersect.start;
primaryRayAtmosphereIntersect.start = max(primaryRayAtmosphereIntersect.start, 0.0);

primaryRayAtmosphereIntersect.stop = min(primaryRayAtmosphereIntersect.stop, length(primaryRayLength));

float x_o_a = start_0 - ATMOSPHERE_THICKNESS; 
float w_inside_atmosphere = 1.0 - 0.5 * (1.0 + czm_approximateTanh(x_o_a));
int PRIMARY_STEPS = PRIMARY_STEPS_MAX - int(w_inside_atmosphere * 12.0); 
int LIGHT_STEPS = LIGHT_STEPS_MAX - int(w_inside_atmosphere * 2.0); 

float rayPositionLength = primaryRayAtmosphereIntersect.start;

float totalRayLength = primaryRayAtmosphereIntersect.stop - rayPositionLength;
float rayStepLengthIncrease = w_inside_atmosphere * ((1.0 - w_stop_gt_lprl) * totalRayLength / (float(PRIMARY_STEPS * (PRIMARY_STEPS + 1)) / 2.0));
float rayStepLength = max(1.0 - w_inside_atmosphere, w_stop_gt_lprl) * totalRayLength / max(7.0 * w_inside_atmosphere, float(PRIMARY_STEPS));

vec3 rayleighAccumulation = vec3(0.0);
vec3 mieAccumulation = vec3(0.0);
vec2 opticalDepth = vec2(0.0);
vec2 heightScale = vec2(czm_atmosphereRayleighScaleHeight, czm_atmosphereMieScaleHeight);

for (int i = 0; i < PRIMARY_STEPS_MAX; ++i) {

    if (i >= PRIMARY_STEPS) {
        break;
    }

    vec3 samplePosition = primaryRay.origin + primaryRay.direction * (rayPositionLength + rayStepLength);

    float sampleHeight = length(samplePosition) - atmosphereInnerRadius;

    vec2 sampleDensity = exp(-sampleHeight / heightScale) * rayStepLength;
    opticalDepth += sampleDensity;

    czm_ray lightRay = czm_ray(samplePosition, lightDirection);
    czm_raySegment lightRayAtmosphereIntersect = czm_raySphereIntersectionInterval(lightRay, origin, atmosphereOuterRadius);

    float lightStepLength = lightRayAtmosphereIntersect.stop / float(LIGHT_STEPS);
    float lightPositionLength = 0.0;

    vec2 lightOpticalDepth = vec2(0.0);

    for (int j = 0; j < LIGHT_STEPS_MAX; ++j) {

        if (j >= LIGHT_STEPS) {
            break;
        }

        vec3 lightPosition = samplePosition + lightDirection * (lightPositionLength + lightStepLength * 0.5);

        float lightHeight = length(lightPosition) - atmosphereInnerRadius;

        lightOpticalDepth += exp(-lightHeight / heightScale) * lightStepLength;

        lightPositionLength += lightStepLength;
    }

    vec3 attenuation = exp(-((czm_atmosphereMieCoefficient * (opticalDepth.y + lightOpticalDepth.y)) + (czm_atmosphereRayleighCoefficient * (opticalDepth.x + lightOpticalDepth.x))));

    rayleighAccumulation += sampleDensity.x * attenuation;
    mieAccumulation += sampleDensity.y * attenuation;

    rayPositionLength += (rayStepLength += rayStepLengthIncrease);
}

rayleighColor = czm_atmosphereRayleighCoefficient * rayleighAccumulation;
mieColor = czm_atmosphereMieCoefficient * mieAccumulation;

opacity = length(exp(-((czm_atmosphereMieCoefficient * opticalDepth.y) + (czm_atmosphereRayleighCoefficient * opticalDepth.x))));

}

uniform vec3 czm_viewerPositionWC; uniform vec3 czm_sunDirectionWC; uniform vec3 czm_lightDirectionWC;

ifdef LOG_DEPTH

out float v_depthFromNearPlusOne;

ifdef SHADOW_MAP

out vec3 v_logPositionEC;

endif

endif

vec4 czm_updatePositionDepth(vec4 coords) {

if defined(LOG_DEPTH)

ifdef SHADOW_MAP

vec3 logPositionEC = (czm_inverseProjection * coords).xyz;
v_logPositionEC = logPositionEC;

endif

coords.z = clamp(coords.z / coords.w, -1.0, 1.0) * coords.w;

endif

return coords;

}

void czm_vertexLogDepth() {

ifdef LOG_DEPTH

v_depthFromNearPlusOne = (gl_Position.w - czm_currentFrustum.x) + 1.0;
gl_Position = czm_updatePositionDepth(gl_Position);

endif

}

void czm_vertexLogDepth(vec4 clipCoords) {

ifdef LOG_DEPTH

v_depthFromNearPlusOne = (clipCoords.w - czm_currentFrustum.x) + 1.0;
czm_updatePositionDepth(clipCoords);

endif

}

uniform mat3 czm_normal; uniform mat4 czm_modelView; uniform mat3 czm_normal3D; uniform mat4 czm_modelView3D;

struct czm_modelVertexOutput { vec3 positionMC; float pointSize; };

const float czm_passTranslucent = 8.0;

uniform float czm_pass; uniform mat4 czm_model; uniform mat4 czm_projection;

void czm_computeGroundAtmosphereScattering(vec3 positionWC, vec3 lightDirection, out vec3 rayleighColor, out vec3 mieColor, out float opacity) { vec3 cameraToPositionWC = positionWC - czm_viewerPositionWC; vec3 cameraToPositionWCDirection = normalize(cameraToPositionWC); czm_ray primaryRay = czm_ray(czm_viewerPositionWC, cameraToPositionWCDirection);

float atmosphereInnerRadius = length(positionWC);

czm_computeScattering(
    primaryRay,
    length(cameraToPositionWC),
    lightDirection,
    atmosphereInnerRadius,
    rayleighColor,
    mieColor,
    opacity
);

}

uniform float czm_atmosphereDynamicLighting;

vec3 czm_getDynamicAtmosphereLightDirection(vec3 positionWC, float lightEnum) { const float NONE = 0.0; const float SCENE_LIGHT = 1.0; const float SUNLIGHT = 2.0;

vec3 lightDirection =
    positionWC * float(lightEnum == NONE) +
    czm_lightDirectionWC * float(lightEnum == SCENE_LIGHT) +
    czm_sunDirectionWC * float(lightEnum == SUNLIGHT);
return normalize(lightDirection);

}

float czm_round(float value) { return floor(value + 0.5); }

vec2 czm_round(vec2 value) { return floor(value + 0.5); }

vec3 czm_round(vec3 value) { return floor(value + 0.5); }

vec4 czm_round(vec4 value) { return floor(value + 0.5); }

line 0

in vec3 a_positionMC; in vec3 a_normalMC; in vec2 a_texCoord_0; in float a_featureId_0; uniform int model_featuresLength; uniform sampler2D model_batchTexture; uniform vec4 model_textureStep; uniform bool model_commandTranslucent; out vec3 v_atmosphereRayleighColor; out vec3 v_atmosphereMieColor; out float v_atmosphereOpacity; out vec3 v_positionWC; out vec3 v_positionEC; out vec3 v_positionMC; out vec3 v_normalEC; out vec2 v_texCoord_0; out float v_featureId_0; struct ProcessedAttributes { vec3 positionMC; vec3 normalMC; vec2 texCoord_0; float featureId_0; }; struct SelectedFeature { int id; vec2 st; vec4 color; }; struct FeatureIds { int featureId_0; }; struct Metadata { float _empty; }; struct MetadataClass { float _empty; }; struct MetadataStatistics { float _empty; }; void initializeAttributes(out ProcessedAttributes attributes) { attributes.positionMC = a_positionMC; attributes.normalMC = a_normalMC; attributes.texCoord_0 = a_texCoord_0; attributes.featureId_0 = a_featureId_0; } void setDynamicVaryings(inout ProcessedAttributes attributes) { v_texCoord_0 = attributes.texCoord_0; v_featureId_0 = attributes.featureId_0; } void initializeFeatureIds(out FeatureIds featureIds, ProcessedAttributes attributes) { featureIds.featureId_0 = int(czm_round(attributes.featureId_0)); } void initializeFeatureIdAliases(inout FeatureIds featureIds) { } void setFeatureIdVaryings() { } void initializeMetadata(out Metadata metadata, out MetadataClass metadataClass, out MetadataStatistics metadataStatistics, ProcessedAttributes attributes) { } void setMetadataVaryings() { } void atmosphereStage(ProcessedAttributes attributes) { vec3 lightDirection = czm_getDynamicAtmosphereLightDirection(v_positionWC, czm_atmosphereDynamicLighting);

czm_computeGroundAtmosphereScattering(

    v_positionWC,
    lightDirection,
    v_atmosphereRayleighColor,
    v_atmosphereMieColor,
    v_atmosphereOpacity
);

}

vec4 geometryStage(inout ProcessedAttributes attributes, mat4 modelView, mat3 normal) { vec4 computedPosition;

vec3 positionMC = attributes.positionMC;
v_positionMC = positionMC;
v_positionEC = (modelView * vec4(positionMC, 1.0)).xyz;

#if defined(USE_2D_POSITIONS) || defined(USE_2D_INSTANCING)
vec3 position2D = attributes.position2D;
vec3 positionEC = (u_modelView2D * vec4(position2D, 1.0)).xyz;
computedPosition = czm_projection * vec4(positionEC, 1.0);
#else
computedPosition = czm_projection * vec4(v_positionEC, 1.0);
#endif

#if defined(COMPUTE_POSITION_WC_CUSTOM_SHADER) || defined(COMPUTE_POSITION_WC_STYLE) || defined(COMPUTE_POSITION_WC_ATMOSPHERE)

v_positionWC = (czm_model * vec4(positionMC, 1.0)).xyz;
#endif

#ifdef HAS_NORMALS
v_normalEC = normalize(normal * attributes.normalMC);
#endif

#ifdef HAS_TANGENTS
v_tangentEC = normalize(normal * attributes.tangentMC);
#endif

#ifdef HAS_BITANGENTS
v_bitangentEC = normalize(normal * attributes.bitangentMC);
#endif

setDynamicVaryings(attributes);

return computedPosition;

}

void featureIdStage(out FeatureIds featureIds, ProcessedAttributes attributes) { initializeFeatureIds(featureIds, attributes); initializeFeatureIdAliases(featureIds); setFeatureIdVaryings(); }

void metadataStage( out Metadata metadata, out MetadataClass metadataClass, out MetadataStatistics metadataStatistics, ProcessedAttributes attributes ) { initializeMetadata(metadata, metadataClass, metadataStatistics, attributes); setMetadataVaryings(); }

vec2 computeSt(float featureId) { float stepX = model_textureStep.x; float centerX = model_textureStep.y;

#ifdef MULTILINE_BATCH_TEXTURE
float stepY = model_textureStep.z;
float centerY = model_textureStep.w;

float xId = mod(featureId, model_textureDimensions.x); 
float yId = floor(featureId / model_textureDimensions.x);

return vec2(centerX + (xId * stepX), centerY + (yId * stepY));
#else
return vec2(centerX + (featureId * stepX), 0.5);
#endif

}

void selectedFeatureIdStage(out SelectedFeature feature, FeatureIds featureIds) {
int featureId = featureIds.SELECTED_FEATURE_ID;

if (featureId < model_featuresLength)
{
    vec2 featureSt = computeSt(float(featureId));

    feature.id = featureId;
    feature.st = featureSt;
    feature.color = texture(model_batchTexture, featureSt);
}

else
{
    feature.id = model_featuresLength + 1;
    feature.st = vec2(0.0);
    feature.color = vec4(1.0);
}

#ifdef HAS_NULL_FEATURE_ID
if (featureId == model_nullFeatureId) {
    feature.id = featureId;
    feature.st = vec2(0.0);
    feature.color = vec4(1.0);
}
#endif

}

void filterByPassType(inout vec3 positionMC, vec4 featureColor) { bool styleTranslucent = (featureColor.a != 1.0);

if (czm_pass == czm_passTranslucent && !styleTranslucent && !model_commandTranslucent)
{

    #ifdef HAS_SILHOUETTE
    positionMC *= float(model_silhouettePass);
    #else
    positionMC *= 0.0;
    #endif
}

else if (czm_pass != czm_passTranslucent && styleTranslucent)
{
    positionMC *= 0.0;
}

}

void cpuStylingStage(inout vec3 positionMC, inout SelectedFeature feature) { float show = ceil(feature.color.a); positionMC *= show;

#if defined(HAS_SELECTED_FEATURE_ID_ATTRIBUTE) && !defined(HAS_CLASSIFICATION)
filterByPassType(positionMC, feature.color);
#endif

}

czm_modelVertexOutput defaultVertexOutput(vec3 positionMC) { czm_modelVertexOutput vsOutput; vsOutput.positionMC = positionMC; vsOutput.pointSize = 1.0; return vsOutput; }

void czm_log_depth_main() {

ProcessedAttributes attributes;
initializeAttributes(attributes);

#ifdef USE_DEQUANTIZATION
dequantizationStage(attributes);
#endif

#ifdef HAS_MORPH_TARGETS
morphTargetsStage(attributes);
#endif

#ifdef HAS_SKINNING
skinningStage(attributes);
#endif

#ifdef HAS_PRIMITIVE_OUTLINE
primitiveOutlineStage();
#endif

#ifdef HAS_BITANGENTS
attributes.bitangentMC = normalize(cross(attributes.normalMC, attributes.tangentMC) * attributes.tangentSignMC);
#endif

FeatureIds featureIds;
featureIdStage(featureIds, attributes);

#ifdef HAS_SELECTED_FEATURE_ID
SelectedFeature feature;
selectedFeatureIdStage(feature, featureIds);

cpuStylingStage(attributes.positionMC, feature);
#endif

#if defined(USE_2D_POSITIONS) || defined(USE_2D_INSTANCING)

mat4 modelView = czm_modelView3D;
mat3 normal = czm_normal3D;
#else

mat4 modelView = czm_modelView;
mat3 normal = czm_normal;
#endif

#ifdef HAS_INSTANCING

    #ifdef USE_LEGACY_INSTANCING
    mat4 instanceModelView;
    mat3 instanceModelViewInverseTranspose;

    legacyInstancingStage(attributes, instanceModelView, instanceModelViewInverseTranspose);

    modelView = instanceModelView;
    normal = instanceModelViewInverseTranspose;
    #else
    instancingStage(attributes);
    #endif

    #ifdef USE_PICKING
    v_pickColor = a_pickColor;
    #endif

#endif

Metadata metadata;
MetadataClass metadataClass;
MetadataStatistics metadataStatistics;
metadataStage(metadata, metadataClass, metadataStatistics, attributes);

#ifdef HAS_VERTICAL_EXAGGERATION
verticalExaggerationStage(attributes);
#endif

#ifdef HAS_CUSTOM_VERTEX_SHADER
czm_modelVertexOutput vsOutput = defaultVertexOutput(attributes.positionMC);
customShaderStage(vsOutput, attributes, featureIds, metadata, metadataClass, metadataStatistics);
#endif

vec4 positionClip = geometryStage(attributes, modelView, normal);

#ifdef HAS_ATMOSPHERE
atmosphereStage(attributes);
#endif

#ifdef HAS_SILHOUETTE
silhouetteStage(attributes, positionClip);
#endif

#ifdef HAS_POINT_CLOUD_SHOW_STYLE
float show = pointCloudShowStylingStage(attributes, metadata);
#else
float show = 1.0;
#endif

#ifdef HAS_POINT_CLOUD_BACK_FACE_CULLING
show *= pointCloudBackFaceCullingStage();
#endif

#ifdef HAS_POINT_CLOUD_COLOR_STYLE
v_pointCloudColor = pointCloudColorStylingStage(attributes, metadata);
#endif

#ifdef PRIMITIVE_TYPE_POINTS
    #ifdef HAS_CUSTOM_VERTEX_SHADER
    gl_PointSize = vsOutput.pointSize;
    #elif defined(HAS_POINT_CLOUD_POINT_SIZE_STYLE) || defined(HAS_POINT_CLOUD_ATTENUATION)
    gl_PointSize = pointCloudPointSizeStylingStage(attributes, metadata);
    #else
    gl_PointSize = 1.0;
    #endif

    gl_PointSize *= show;
#endif

gl_Position = show * positionClip;

}

line 0

void czm_non_renderPass_OutlineEffectPass_main() { czm_log_depth_main(); czm_vertexLogDepth(); }

line 0

vec3 packNormalToRGB(const in vec3 normal) { return normalize(normal) * 0.5 + 0.5; }

vec3 unpackRGBToNormal(const in vec3 rgb) { return 2.0 * rgb.xyz - 1.0; }

const float PackUpscale = 256. / 255.; const float UnpackDownscale = 255. / 256.;

const vec3 PackFactors = vec3(256. 256. 256., 256. * 256., 256.); const vec4 UnpackFactors = UnpackDownscale / vec4(PackFactors, 1.);

const float ShiftRight8 = 1. / 256.;

vec4 packDepthToRGBA(const in float v) { vec4 r = vec4(fract(v PackFactors), v); r.yzw -= r.xyz ShiftRight8; return r * PackUpscale; }

float unpackRGBAToDepth(const in vec4 v) { return dot(v, UnpackFactors); }

vec4 pack2HalfToRGBA(vec2 v) { vec4 r = vec4(v.x, fract(v.x 255.0), v.y, fract(v.y 255.0)); return vec4(r.x - r.y / 255.0, r.y, r.z - r.w / 255.0, r.w); } vec2 unpackRGBATo2Half(vec4 v) { return vec2(v.x + (v.y / 255.0), v.z + (v.w / 255.0)); }

float viewZToOrthographicDepth(const in float viewZ, const in float near, const in float far) { return (viewZ + near) / (near - far); } float orthographicDepthToViewZ(const in float linearClipZ, const in float near, const in float far) { return linearClipZ * (near - far) - near; }

float viewZToPerspectiveDepth(const in float viewZ, const in float near, const in float far) { return ((near + viewZ) far) / ((far - near) viewZ); } float perspectiveDepthToViewZ(const in float invClipZ, const in float near, const in float far) { return (near far) / ((far - near) invClipZ - far); }

uniform sampler2D czm_selectedIdTexture; uniform float czm_selectedIdTextureStep; uniform float czm_selectedIdTextureWidth;

bool czm_selected(vec4 id) { bool selected = false; for (int i = 0; i < 1024000; i++) { vec4 selectedId = texture(czm_selectedIdTexture, vec2((float(i) + 0.5) * czm_selectedIdTextureStep, 0.5)); if(all(equal(id, selectedId))) { return true; } if(float(i) > czm_selectedIdTextureWidth) break; } return false; } out float me_isSelected; bool czm_selected() { return czm_selected(((selectedFeature.id < int(model_featuresLength)) ? texture(model_pickTexture, selectedFeature.st) : vec4(0.0))); }

  out vec3 vOutlineNormal;
  void czm_renderPass_OutlineEffectPass_main() {
    #ifdef HAS_NORMAL
      vOutlineNormal = normal;
    #else
      #ifdef HAS_V_NORMAL
        vOutlineNormal = v_normal;
      #else
        vOutlineNormal = vec3(0.);
      #endif
    #endif
  }
  void main() 

{ czm_non_renderPass_OutlineEffectPass_main(); me_isSelected = czm_selected() ? 1. : 0.; czm_renderPass_OutlineEffectPass_main(); }

syzdev commented 5 months ago

Hi @HKEFU , please supplement the version information, and then provide relevant sandcastle or tileset to help you better track the issue.

It seems that the issue lies in this piece of code: https://github.com/CesiumGS/cesium/blob/db62d077950f4fad4fc73ed50c08144ae724fa90/packages/engine/Source/Scene/Model/PickingPipelineStage.js#L158-L161

HKEFU commented 5 months ago

The cesium version is 1.116.0。 tileset.zip Please refer to this article。 https://zhuanlan.zhihu.com/p/407871786 @syzdev

ggetz commented 5 months ago

Hi @HKEFU. As @syzdev suggested, would you be able to include a Sandcastle example that replicates the issue? That would help us give us more context to determine the issue. Thanks!

HKEFU commented 5 months ago

Hi @ggetz. This zip file is the sample code, and the video shows this error message.Thanks! example.zip

video url: https://github.com/CesiumGS/cesium/assets/169979994/e3f4f705-2d14-41ce-9865-a533a4fe191f

ggetz commented 5 months ago

Hi @HKEFU, I identified a few errors with the linked tileset using the 3D Tiles Validator tool. I'd suggest running the tool and fixing any errors.