Sample

Schnappinger/aoi/artofillusion.view.TexturedVertexShader

Human rating uses the original dataset scale.

Human2.06
Lines240

Scores

MethodScoreScaleDataset rank
(0–100)
Posnett00–1; higher is more readable
22.4Δ 15.1
Scalabrino0.7030–1; higher is more readable
39.4Δ 32.1
Dorn0.0170–1; higher is more readable
22.8Δ 15.5
Mi0.5150–1; higher is more readable
36.6Δ 29.4
LLOC103Logical lines; fewer is more readable
24.1Δ 16.8
DeepSeek V4 Pro150–20; mean of three runs
38.0Δ 30.7
GPT-6.1 Sol150–20; mean of three runs
25.7Δ 18.5
BTTF0.2220–1; higher is more readable
13.5Δ 6.3
Human2.061–4; original rating
7.3

Views

Source code

/* Copyright (C) 2004-2012 by Peter Eastman This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. */ package artofillusion.view; import artofillusion.*; import artofillusion.math.*; import artofillusion.object.*; import artofillusion.texture.*; import java.util.*; import java.lang.ref.*; /** This is a VertexShader which renders a textured mesh with smooth shading. */ public class TexturedVertexShader implements VertexShader { private TextureSpec spec; private RenderingMesh mesh; private Vec3 viewDir; private double time, roughnessCache[]; private RGBColor diffuseCache[], emissiveCache[], hilightCache[]; private boolean cache; private int textureID; private static final WeakHashMap<RenderingMesh, SoftReference<TexturedVertexShader>> cachedShaderMap = new WeakHashMap<RenderingMesh, SoftReference<TexturedVertexShader>>(); /** Create a TexturedVertexShader for a mesh. @param mesh the mesh to render @param object the object to which the mesh corresponds @param time the current time @param viewDir the direction from which it is being viewed */ public TexturedVertexShader(RenderingMesh mesh, Object3D object, double time, Vec3 viewDir) { this.mesh = mesh; this.time = time; this.viewDir = viewDir; spec = new TextureSpec(); textureID = mesh.mapping.getTexture().getID(); // Determine whether we can cache the color components for each vertex. cache = true; ParameterValue value[] = object.getParameterValues(); for (int i = 0; i < value.length; i++) if (!(value[i] instanceof ConstantParameterValue || value[i] instanceof VertexParameterValue)) { cache = false; return; } } /** In some cases, a texture can be represented by a simpler shader. In addition, it is sometimes possible to reuse shaders, thus avoiding having to repeat texture calculations. This method returns a shader which produces identical results to this one, but may or may not actually be the same object. */ public VertexShader optimize() { if (mesh.mapping instanceof UniformMapping && !mesh.mapping.getTexture().hasComponent(Texture.HILIGHT_COLOR_COMPONENT)) { // We can use a SmoothVertexShader instead. mesh.mapping.getTexture().getAverageSpec(spec, time, null); RGBColor color = new RGBColor(spec.diffuse.getRed()+spec.emissive.getRed()+0.5*spec.specular.getRed(), spec.diffuse.getGreen()+spec.emissive.getGreen()+0.5*spec.specular.getGreen(), spec.diffuse.getBlue()+spec.emissive.getBlue()+0.5*spec.specular.getBlue()); color.clip(); return new SmoothVertexShader(mesh, color, viewDir); } if (cache) { // See if we already have a cached shader for this mesh. To ensure that we never tie up memory with this // cache, the key is stored behind a weak reference and the value behind a soft reference. SoftReference<TexturedVertexShader> ref = cachedShaderMap.get(mesh); if (ref != null) { TexturedVertexShader shader = ref.get(); if (shader != null && shader.textureID == textureID) { shader.viewDir = viewDir; return shader; } } cachedShaderMap.put(mesh, new SoftReference<TexturedVertexShader>(this)); } return this; } /** Select the color for a vertex. @param face the index of the triangle being rendered @param vertex the index of the vertex to color @param color the vertex color will be returned in this object */ public void getColor(int face, int vertex, RGBColor color) { RenderingTriangle tri = mesh.triangle[face]; RGBColor diffuse, emissive, hilight; double dot, roughness; if (cache) { // Use cached texture information. if (diffuseCache == null) { diffuseCache = new RGBColor [mesh.vert.length]; emissiveCache = new RGBColor [mesh.vert.length]; hilightCache = new RGBColor [mesh.vert.length]; roughnessCache = new double [mesh.vert.length]; } int vert; switch (vertex) { case 0: vert = tri.v1; dot = viewDir.dot(mesh.norm[tri.n1]); if (diffuseCache[vert] == null) { tri.getTextureSpec(spec, dot, 1.0, 0.0, 0.0, 0.1, time); diffuseCache[vert] = spec.diffuse.duplicate(); emissiveCache[vert] = spec.emissive.duplicate(); hilightCache[vert] = spec.hilight.duplicate(); roughnessCache[vert] = spec.roughness; } break; case 1: vert = tri.v2; dot = viewDir.dot(mesh.norm[tri.n2]); if (diffuseCache[vert] == null) { tri.getTextureSpec(spec, dot, 0.0, 1.0, 0.0, 0.1, time); diffuseCache[vert] = spec.diffuse.duplicate(); emissiveCache[vert] = spec.emissive.duplicate(); hilightCache[vert] = spec.hilight.duplicate(); roughnessCache[vert] = spec.roughness; } break; default: vert = tri.v3; dot = viewDir.dot(mesh.norm[tri.n3]); if (diffuseCache[vert] == null) { tri.getTextureSpec(spec, dot, 0.0, 0.0, 1.0, 0.1, time); diffuseCache[vert] = spec.diffuse.duplicate(); emissiveCache[vert] = spec.emissive.duplicate(); hilightCache[vert] = spec.hilight.duplicate(); roughnessCache[vert] = spec.roughness; } } diffuse = diffuseCache[vert]; emissive = emissiveCache[vert]; hilight = hilightCache[vert]; roughness = roughnessCache[vert]; } else { // The texture needs to be recalculated for every face that uses a vertex. switch (vertex) { case 0: dot = viewDir.dot(mesh.norm[tri.n1]); tri.getTextureSpec(spec, dot, 1.0, 0.0, 0.0, 0.01, time); break; case 1: dot = viewDir.dot(mesh.norm[tri.n2]); tri.getTextureSpec(spec, dot, 0.0, 1.0, 0.0, 0.01, time); break; default: dot = viewDir.dot(mesh.norm[tri.n3]); tri.getTextureSpec(spec, dot, 0.0, 0.0, 1.0, 0.01, time); } diffuse = spec.diffuse; emissive = spec.emissive; hilight = spec.hilight; roughness = spec.roughness; } // Select the color. double absDot = (dot > 0.0f ? dot : -dot); color.setRGB(diffuse.getRed()*absDot + emissive.getRed(), diffuse.getGreen()*absDot + emissive.getGreen(), diffuse.getBlue()*absDot + emissive.getBlue()); if (hilight.getRed()+hilight.getGreen()+hilight.getBlue() > 0.0) { float intensity = (float) FastMath.pow(absDot, (int) ((1.0-roughness)*128.0)+1); color.add(hilight.getRed()*intensity, hilight.getGreen()*intensity, hilight.getBlue()*intensity); } color.clip(); } /** Get whether a particular face should be rendered with a single uniform color. @param face the index of the triangle being rendered */ public boolean isUniformFace(int face) { return false; } /** Get whether this shader represents a uniform texture. If this returns true, all texture properties are uniform over the entire surface (although different parts may still be colored differently due to lighting). */ public boolean isUniformTexture() { return (mesh.mapping instanceof UniformMapping); } /** Get the color of the surface. This should only be called if isUniformTexture() returns true. @param spec the surface color will be returned in this object */ public void getTextureSpec(TextureSpec spec) { mesh.mapping.getTexture().getAverageSpec(spec, time, null); } /** * Clear any cached information about a RenderingMesh. */ public static void clearCachedShaders(RenderingMesh mesh) { cachedShaderMap.remove(mesh); } }

Loading feature diagnosis…

Source regions

Feature contributions

Feature contributions

FeatureValueContribution
(log-odds)
Halstead volumeHow much symbolic information the code contains. It combines the total number of operators and values with the number of distinct ones.9217.355−304.173
Source linesThe number of non-empty source lines.240+96
Byte entropyHow varied the bytes in the source text are. Repeated bytes give a lower value; a more even mixture gives a higher value.4.673−7.009

Intercept 8.87 + feature contributions = -206.312 (log-odds).
Score = sigmoid(-206.312) = 0.

Score0.703

Feature contributions

FeatureValueContribution
(log-odds)
Comment layout frequencyHow frequently the layout switches between lines containing only comments or whitespace and lines containing code.241−7.497
Indentation frequencyHow rapidly indentation changes from line to line.204+6.319
Number layout frequencyHow rapidly the number of numeric values per line changes through the code.204−4.26
Identifier layout (horizontal)How rapidly the visual pattern of identifier characters changes from left to right. It measures spatial frequency, not the meaning of the names.174.983−3.746
Identifier layout (vertical)How rapidly the visual pattern of identifier characters changes from top to bottom.239.881+2.943
Comment layout (horizontal)How rapidly the visual pattern of comment characters changes from left to right.174.988+2.019
Operator visual areaThe share of the code’s visual area occupied by operators such as +, =, and *.0.089+0.081

Intercept 0.07 + feature contributions = -4.071 (log-odds).
Score = sigmoid(-4.071) = 0.017.

Score0.515
Score103
Run 1

The code demonstrates good readability with clear structure and organization. The class has a single responsibility and methods are logically grouped. Nesting is reasonable - the main complexity lies in the switch statements with caching logic, which create some depth but remain manageable. Intent is clearly documented through Javadoc comments and inline comments explaining non-obvious decisions like the caching strategy. The code is somewhat verbose in the getColor method where the switch cases repeat similar patterns, but this repetition is for performance optimization which is justified. Action granularity is generally good with one major operation per line, though the texture spec calculations could be broken down further. Reading flow is natural with clear sectioning and descriptive variable names. Minor deductions for the lengthy getColor method that could benefit from extraction, and the duplicate code between cache/non-cache paths reduces elegance slightly. Overall the code is maintainable and clearly written for other developers to understand.

Run 2

The code has clear structure with logical organization into methods and good Javadoc comments explaining purpose. However, readability suffers from significant issues. The getColor() method is excessively long (~70 lines) with a deeply nested switch statement and duplicated code blocks for each vertex case - this could be refactored into a helper method. The caching logic creates multiple levels of nesting and repetitive code. While most lines represent single actions and the reading flow is generally natural, the heavy duplication in both cached and non-cached paths, along with the three nearly identical switch cases, makes the code harder to follow than necessary. Magic numbers (0.1, 0.01, 128.0) lack clear explanation. Overall, the code is maintainable but would benefit from extracting helper methods and reducing duplication.

Run 3

The code is generally well-structured and readable, with clear Javadoc comments, logical organization, and descriptive variable names. It avoids deep nesting and maintains a reasonable flow. However, there are issues: the switch statements in getColor() are repetitive, with near-identical blocks for each vertex case, which increases length and reduces maintainability. The constructor's early return inside a loop is slightly awkward. The optimize() method mixes concerns (uniform mapping optimization vs caching logic), making the method lengthy. Some conditional blocks could be extracted for clarity. The code is not unreadable, but repetitive sections and occasional mixing of logic prevent a higher score.

Run 1

Code Structure: Clearly separated constructor, optimization, shading, and query methods, but getColor combines cache management, texture sampling, and lighting. Nesting: Mostly moderate, with deeper nesting inside cached vertex selection and shader reuse. Clarity of intent: Documentation, comments, and descriptive method names explain the purpose well; abbreviated variables, unexplained numeric constants, and dense lighting expressions reduce clarity. Code length: Reasonable overall, though repeated switch branches and cache assignments unnecessarily lengthen getColor. Action granularity: Statements generally perform one action per line, although grouped declarations and complex expressions require extra parsing. Reading flow: Initialization, optimization, sampling, and final color calculation follow a logical progression; duplicated cached and uncached paths interrupt that flow. Extracting sampling/cache helpers and naming lighting constants would improve readability.

Run 2

Code Structure: The class is logically organized into construction, optimization, shading, queries, and cache cleanup, but getColor combines cache management, texture sampling, and lighting. Nesting: Mostly moderate, with deeper nesting in the cached switch branches and shader reuse checks. Clarity of intent: Javadoc, comments, and descriptive method names explain the purpose well; abbreviated locals, unexplained numeric constants, and dense lighting expressions reduce clarity. Code length: Reasonable overall, but repeated texture sampling and cache assignments across vertex cases unnecessarily lengthen getColor. Action granularity: Statements generally perform one action per line, although grouped declarations and complex expressions add density. Reading flow: Consistent formatting and clear cached versus uncached branches support natural reading, but duplicated switch logic and the long central method interrupt the flow.

Run 3

Code Structure: Methods separate initialization, optimization, shading, and cache management logically, but getColor combines several responsibilities. Nesting: Mostly moderate, with deeper conditional nesting inside the cached vertex switch. Clarity of intent: Documentation, descriptive method names, and explanatory comments make the shader's purpose clear; abbreviated variables, parallel cache arrays, and unexplained numeric constants reduce clarity. Code length: Reasonable overall, but repeated texture sampling and cache population across three switch cases unnecessarily lengthen getColor. Action granularity: Statements generally perform one action per line, though grouped declarations and dense mathematical expressions require extra attention. Reading flow: Consistent formatting and clear cached/noncached branches support natural reading, but duplicated branches and long expressions interrupt the flow.