123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162 |
- /**
- * Copyright (c) 2018-2020 mol* contributors, licensed under MIT, See LICENSE file for more info.
- *
- * @author Alexander Rose <alexander.rose@weirdbyte.de>
- */
- import { Vec3, Mat4, Mat3 } from '../mol-math/linear-algebra'
- import { NumberArray } from '../mol-util/type-helpers';
- import { arrayMax } from '../mol-util/array';
- export function normalizeVec3Array<T extends NumberArray> (a: T, count: number) {
- for (let i = 0, il = count * 3; i < il; i += 3) {
- const x = a[i]
- const y = a[i + 1]
- const z = a[i + 2]
- const s = 1 / Math.sqrt(x * x + y * y + z * z)
- a[i] = x * s
- a[i + 1] = y * s
- a[i + 2] = z * s
- }
- return a
- }
- const tmpV3 = Vec3.zero()
- export function transformPositionArray (t: Mat4, array: NumberArray, offset: number, count: number) {
- for (let i = 0, il = count * 3; i < il; i += 3) {
- Vec3.fromArray(tmpV3, array, offset + i)
- Vec3.transformMat4(tmpV3, tmpV3, t)
- Vec3.toArray(tmpV3, array, offset + i)
- }
- }
- export function transformDirectionArray (n: Mat3, array: NumberArray, offset: number, count: number) {
- for (let i = 0, il = count * 3; i < il; i += 3) {
- Vec3.fromArray(tmpV3, array, offset + i)
- Vec3.transformMat3(tmpV3, tmpV3, n)
- Vec3.toArray(tmpV3, array, offset + i)
- }
- }
- /** iterate over the entire array and apply the radius to each vertex */
- export function appplyRadius(vertices: NumberArray, radius: number) {
- for (let i = 0, il = vertices.length; i < il; i += 3) {
- Vec3.fromArray(tmpV3, vertices, i)
- Vec3.normalize(tmpV3, tmpV3)
- Vec3.scale(tmpV3, tmpV3, radius)
- Vec3.toArray(tmpV3, vertices, i)
- }
- }
- const a = Vec3()
- const b = Vec3()
- const c = Vec3()
- const cb = Vec3()
- const ab = Vec3()
- /**
- * indexed vertex normals weighted by triangle areas
- * http://www.iquilezles.org/www/articles/normals/normals.htm
- * - normals array must contain only zeros
- */
- export function computeIndexedVertexNormals<T extends NumberArray> (vertices: NumberArray, indices: NumberArray, normals: T, vertexCount: number, triangleCount: number) {
- for (let i = 0, il = triangleCount * 3; i < il; i += 3) {
- const ai = indices[i] * 3
- const bi = indices[i + 1] * 3
- const ci = indices[i + 2] * 3
- Vec3.fromArray(a, vertices, ai)
- Vec3.fromArray(b, vertices, bi)
- Vec3.fromArray(c, vertices, ci)
- Vec3.sub(cb, c, b)
- Vec3.sub(ab, a, b)
- Vec3.cross(cb, cb, ab)
- normals[ai] += cb[0]
- normals[ai + 1] += cb[1]
- normals[ai + 2] += cb[2]
- normals[bi] += cb[0]
- normals[bi + 1] += cb[1]
- normals[bi + 2] += cb[2]
- normals[ci] += cb[0]
- normals[ci + 1] += cb[1]
- normals[ci + 2] += cb[2]
- }
- return normalizeVec3Array(normals, vertexCount)
- }
- /**
- * vertex normals for unindexed triangle soup
- * - normals array must contain only zeros
- */
- export function computeVertexNormals<T extends NumberArray> (vertices: NumberArray, normals: T, vertexCount: number) {
- for (let i = 0, il = vertexCount * 3; i < il; i += 9) {
- Vec3.fromArray(a, vertices, i)
- Vec3.fromArray(b, vertices, i + 3)
- Vec3.fromArray(c, vertices, i + 6)
- Vec3.sub(cb, c, b)
- Vec3.sub(ab, a, b)
- Vec3.cross(cb, cb, ab)
- normals[i] = cb[0]
- normals[i + 1] = cb[1]
- normals[i + 2] = cb[2]
- normals[i + 3] = cb[0]
- normals[i + 4] = cb[1]
- normals[i + 5] = cb[2]
- normals[i + 6] = cb[0]
- normals[i + 7] = cb[1]
- normals[i + 8] = cb[2]
- }
- return normalizeVec3Array(normals, vertexCount)
- }
- /**
- * Maps groups to data, range for group i is offsets[i] to offsets[i + 1]
- */
- export type GroupMapping = {
- /** data indices */
- readonly indices: ArrayLike<number>
- /** range for group i is offsets[i] to offsets[i + 1] */
- readonly offsets: ArrayLike<number>
- }
- /**
- * The `step` parameter allows to skip over repeated values in `groups`
- */
- export function createGroupMapping(groups: ArrayLike<number>, dataCount: number, step = 1): GroupMapping {
- const maxId = arrayMax(groups)
- const offsets = new Int32Array(maxId + 2)
- const bucketFill = new Int32Array(dataCount)
- const bucketSizes = new Int32Array(dataCount)
- for (let i = 0, il = dataCount * step; i < il; i += step) ++bucketSizes[groups[i]]
- let offset = 0
- for (let i = 0; i < dataCount; i++) {
- offsets[i] = offset
- offset += bucketSizes[i]
- }
- offsets[dataCount] = offset
- const indices = new Int32Array(offset)
- for (let i = 0, il = dataCount * step; i < il; i += step) {
- const g = groups[i]
- const og = offsets[g] + bucketFill[g]
- indices[og] = i
- ++bucketFill[g]
- }
- return { indices, offsets }
- }
|