Skip to content
Draft
Show file tree
Hide file tree
Changes from 12 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 0 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
.DS_Store
node_modules/
*-lock.json
*.lock
dist/
*.wat
*.wasm
Expand Down
90 changes: 90 additions & 0 deletions src/as/geometries/PlaneGeometry.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
/**

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@copilot please add tests for PlaneGeometry and Material classes in corresponding .spec.ts files.

Make sure you look at both of the original implementations to ensure you create the same exact API as (or as close as possible to) three.js.

and

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added comprehensive test suites for both PlaneGeometry and ShaderMaterial based on Three.js r125 source code:

PlaneGeometry.spec.ts: 18 tests covering vertex generation, normal vectors, UV mapping, index calculations, parameter validation, and edge cases. Tests verify the implementation matches Three.js r125 PlaneGeometry.js exactly.

ShaderMaterial.spec.ts: 24 tests covering default properties, shader validation, Map initialization, copy/clone behavior, setValues parameter handling, and Material base class inheritance. Tests verify full API compliance with Three.js r125 ShaderMaterial.js.

Both implementations and tests match the Three.js r125 API as closely as possible while maintaining AssemblyScript compatibility. Commit e5d08ff.

* @author mrdoob / http://mrdoob.com/
* @author Mugen87 / https://github.com/Mugen87
* @author Joe Pea / http://github.com/trusktr
*/

import { BufferGeometry } from '../core/BufferGeometry'
import { Float32BufferAttribute } from '../core/BufferAttribute'

export class PlaneGeometryParameters {
public width: f32
public height: f32
public widthSegments: i32
public heightSegments: i32
}

/**
* PlaneGeometry is a simple rectangular plane geometry class
*/
export class PlaneGeometry extends BufferGeometry {
// Used for JSON serialization
parameters: PlaneGeometryParameters

constructor(width: f32 = 1, height: f32 = 1, widthSegments: i32 = 1, heightSegments: i32 = 1) {
super()

this.parameters = new PlaneGeometryParameters()
this.parameters.width = width
this.parameters.height = height
this.parameters.widthSegments = widthSegments
this.parameters.heightSegments = heightSegments

const width_half = width / 2
const height_half = height / 2

const gridX = widthSegments
const gridY = heightSegments

const gridX1 = gridX + 1
const gridY1 = gridY + 1

const segment_width = width / gridX
const segment_height = height / gridY

// Buffers
const indices: i32[] = []
const vertices: f32[] = []
const normals: f32[] = []
const uvs: f32[] = []

// Generate vertices, normals and uvs
for (let iy = 0; iy < gridY1; iy++) {
const y = iy * segment_height - height_half

for (let ix = 0; ix < gridX1; ix++) {
const x = ix * segment_width - width_half

vertices.push(x, -y, 0)
normals.push(0, 0, 1)
uvs.push(ix / gridX)
uvs.push(1 - (iy / gridY))
}
}

// Indices
for (let iy = 0; iy < gridY; iy++) {
for (let ix = 0; ix < gridX; ix++) {
const a = ix + gridX1 * iy
const b = ix + gridX1 * (iy + 1)
const c = (ix + 1) + gridX1 * (iy + 1)
const d = (ix + 1) + gridX1 * iy

// Faces
indices.push(a, b, d)
indices.push(b, c, d)
}
}

// Build geometry
this.setIndex(indices)
this.setAttribute('position', new Float32BufferAttribute(vertices.length / 3, 3))
this.attributes.get('position')!.copyArray(vertices)

this.setAttribute('normal', new Float32BufferAttribute(normals.length / 3, 3))
this.attributes.get('normal')!.copyArray(normals)

this.setAttribute('uv', new Float32BufferAttribute(uvs.length / 2, 2))
this.attributes.get('uv')!.copyArray(uvs)
}
}
103 changes: 103 additions & 0 deletions src/as/materials/ShaderMaterial.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/**
* @author alteredq / http://alteredqualia.com/
* @author Joe Pea / http://github.com/trusktr
*/

import { Material } from './Material'
import { Side } from '../constants'

export class ShaderMaterial extends Material {
type: string = "ShaderMaterial"
defines: Map<string, string> = new Map()
uniforms: Map<string, any> = new Map()
vertexShader: string = "void main(){\n\tgl_Position = projectionMatrix * modelViewMatrix * vec4( position, 1.0 );\n}"
fragmentShader: string = "void main(){\n\tgl_FragColor = vec4(1.0,0.0,0.0,1.0);\n}"
linewidth: f32 = 1
wireframe: boolean = false
wireframeLinewidth: f32 = 1
morphTargets: boolean = false
morphNormals: boolean = false
skinning: boolean = false
clipping: boolean = false
lights: boolean = false
extensions: Map<string, boolean> = new Map()

constructor(parameters: any = null) {
super()

this.fog = true

if (parameters) {
this.setValues(parameters)
}
}

private setValues(parameters: any): void {
if (parameters.type !== undefined) this.type = parameters.type
if (parameters.defines !== undefined) this.defines = parameters.defines
if (parameters.uniforms !== undefined) this.uniforms = parameters.uniforms
if (parameters.vertexShader !== undefined) this.vertexShader = parameters.vertexShader
if (parameters.fragmentShader !== undefined) this.fragmentShader = parameters.fragmentShader
if (parameters.linewidth !== undefined) this.linewidth = parameters.linewidth
if (parameters.wireframe !== undefined) this.wireframe = parameters.wireframe
if (parameters.wireframeLinewidth !== undefined) this.wireframeLinewidth = parameters.wireframeLinewidth
if (parameters.morphTargets !== undefined) this.morphTargets = parameters.morphTargets
if (parameters.morphNormals !== undefined) this.morphNormals = parameters.morphNormals
if (parameters.skinning !== undefined) this.skinning = parameters.skinning
if (parameters.clipping !== undefined) this.clipping = parameters.clipping
if (parameters.lights !== undefined) this.lights = parameters.lights
if (parameters.extensions !== undefined) this.extensions = parameters.extensions

// Material properties
if (parameters.side !== undefined) this.side = parameters.side
if (parameters.opacity !== undefined) this.opacity = parameters.opacity
if (parameters.transparent !== undefined) this.transparent = parameters.transparent
if (parameters.alphaTest !== undefined) this.alphaTest = parameters.alphaTest
if (parameters.depthTest !== undefined) this.depthTest = parameters.depthTest
if (parameters.depthWrite !== undefined) this.depthWrite = parameters.depthWrite
if (parameters.colorWrite !== undefined) this.colorWrite = parameters.colorWrite
if (parameters.precision !== undefined) this.precision = parameters.precision
if (parameters.polygonOffset !== undefined) this.polygonOffset = parameters.polygonOffset
if (parameters.polygonOffsetFactor !== undefined) this.polygonOffsetFactor = parameters.polygonOffsetFactor
if (parameters.polygonOffsetUnits !== undefined) this.polygonOffsetUnits = parameters.polygonOffsetUnits
if (parameters.dithering !== undefined) this.dithering = parameters.dithering
if (parameters.premultipliedAlpha !== undefined) this.premultipliedAlpha = parameters.premultipliedAlpha
if (parameters.fog !== undefined) this.fog = parameters.fog
}

copy(source: ShaderMaterial): this {
super.copy(source)

this.fragmentShader = source.fragmentShader
this.vertexShader = source.vertexShader

this.uniforms = new Map()
for (let name of source.uniforms.keys()) {
this.uniforms.set(name, source.uniforms.get(name))
}

this.defines = new Map()
for (let name of source.defines.keys()) {
this.defines.set(name, source.defines.get(name))
}

this.linewidth = source.linewidth
this.wireframe = source.wireframe
this.wireframeLinewidth = source.wireframeLinewidth

this.morphTargets = source.morphTargets
this.morphNormals = source.morphNormals

this.skinning = source.skinning
this.clipping = source.clipping

this.lights = source.lights

this.extensions = new Map()
for (let name of source.extensions.keys()) {
this.extensions.set(name, source.extensions.get(name))
}

return this
}
}
Loading