Skip to content

Commit

Permalink
added obj loader
Browse files Browse the repository at this point in the history
  • Loading branch information
manthanabc committed Aug 18, 2024
1 parent eacfe81 commit 1836c6f
Show file tree
Hide file tree
Showing 6 changed files with 15,025 additions and 74 deletions.
132 changes: 58 additions & 74 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,9 @@
border-bottom: 50px solid teal;
}
</style>
<script>
<script type='module'>

import OBJFile from './objparser.js'

let parent = document.getElementById('main');
let tris = [];
Expand All @@ -42,30 +44,31 @@
}
}

let convert2d = ([ox, oy, oz]) => {
<!-- let [x, y ,z] = rotate([ox, oy, oz]) -->
<!-- return [ox + 10, oy + 10, oz + 10] -->
let [x, y, z] = rotate([ox, oy, oz])
let sf = Math.pow(z + 15, 0.2 + 0.0001)
<!-- p2 = new Point2d(x * 20 + 500, y * 20 + 500); -->
<!-- p2.x /= sf; -->
<!-- p2.y /= sf; -->
return [(x*20+500)/sf, (y*20+500)/sf];
}

rotate = (p) => {
let rotate = (p) => {
let angle_rad = angle * Math.PI / 180.0;
<!-- angle_rad = 0; -->
// angle_rad = 0;
let a = [0, 0, 0 ]
let s = Math.sin(angle_rad);
let c =Math.cos(angle_rad);
<!-- z -= 100; -->
// z -= 100;
a[0] = p[0] * c - p[2] * s;
a[1] = p[1] ;
a[2] = p[0] * s + p[2] * c;
return a;
}

let convert2d = ([ox, oy, oz]) => {
// let [x, y ,z] = rotate([ox, oy, oz])
// return [ox + 10, oy + 10, oz + 10]
let [x, y, z] = rotate([ox, oy, oz])
let sf = Math.max(Math.pow(z + 20, 0.3 + 0.01), 1);
// p2 = new Point2d(x * 20 + 500, y * 20 + 500);
// p2.x /= sf;
// p2.y /= sf;
return [(x/sf*20+500), ((y+30)/sf*20+500)];
}


class rendertrig {
constructor(p1, p2, p3) {
this.p1 = p1;
Expand Down Expand Up @@ -130,7 +133,7 @@
tg = new triangle(t3, t1, t2);
}

let y=this.elm//document.getElementsByClassName('trig')[0]
let y=this.elm // document.getElementsByClassName('trig')[0]
let distbase = dist(tg.t2.x, tg.t2.y, tg.t3.x, tg.t3.y);

let sign = (tg.t2.x - tg.t1.x) * (tg.t3.y - tg.t1.y) - (tg.t3.x - tg.t1.x) * (tg.t2.y - tg.t1.y);
Expand Down Expand Up @@ -201,74 +204,55 @@
let angle = 45;


let cube = []
let makecube = () => {

cube.push(new rendertrig(
[ -5, -5, -5],
[ 5, -5, -5],
[ 5, 5, -5]
));
cube.push(new rendertrig(
[ -5, 5, -5],
[ -5, -5, -5],
[ 5, 5, -5]
));

// Define vertices in the z = 5 plane
cube.push(new rendertrig(
[ -5, -5, 5],
[ 5, -5, 5],
[ 5, 5, 5]
));
cube.push(new rendertrig(
[ -5, 5, 5],
[ -5, -5, 5],
[ 5, 5, 5]
));

// Define vertical edges connecting the top and bottom faces
cube.push(new rendertrig(
[ -5, -5, -5],
[ -5, -5, 5],
[ -5, 5, 5]
));
cube.push(new rendertrig(
[ -5, 5, -5],
[ -5, -5, -5],
[ -5, 5, 5]
));
cube.push(new rendertrig(
[ 5, -5, -5],
[ 5, -5, 5],
[ 5, 5, 5]
));
cube.push(new rendertrig(
[ 5, 5, -5],
[ 5, -5, -5],
[ 5, 5, 5]
));
}
let faces = []

for(let i=0; i<200; i++) {
makecube();
}
cube.forEach((trig) => {
let t = await fetch('./teapot.obj')
let tex = await t.text();


const objFile = new OBJFile(tex);
const output = objFile.parse(); // see description below


let model = output.models[0];
let Obj_faces = model.faces;
let vertices = model.vertices;

console.log(vertices.length)
console.log(Obj_faces.length)

Obj_faces.forEach((face) => {
let tex = vertices[face.vertices[0].vertexIndex -1]
let t1 = [tex.x*5 , -tex.y*5 , tex.z*5 ];
tex = vertices[face.vertices[1].vertexIndex -1]
let t2 = [tex.x*5 , -tex.y*5 , tex.z*5 ];
tex = vertices[face.vertices[2].vertexIndex -1]
let t3 = [tex.x*5 , -tex.y*5 , tex.z*5 ];

faces.push(new rendertrig(
t1, t2, t3
))
})

faces.forEach((trig) => {
trig.init();
})
let renderCube = () => {
cube.forEach((trig) => {
faces.forEach((trig) => {
trig.draw();
})
}

renderCube()
document.onmousemove = handleMouseMove;

window.setInterval(() => {
angle += 1;
renderCube();
}, 50)

// document.onmousemove = handleMouseMove;
function handleMouseMove(event) {
if(Math.random() > 0.05) {
var eventDoc, doc, body;
p2x = event.pageX;
p2y = event.pageY;
if(Math.random() > 0.1) {
angle += 1
renderCube();
}
Expand Down
210 changes: 210 additions & 0 deletions objparser.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,210 @@
class OBJFile {
constructor(fileContents, defaultModelName) {
this._reset();
this.fileContents = fileContents;
this.defaultModelName = (defaultModelName || 'untitled');
}

_reset() {
this.result = {
models: [],
materialLibraries: []
};
this.currentMaterial = '';
this.currentGroup = '';
this.smoothingGroup = 0;
}

parse() {
this._reset();

const _stripComments = (lineString) => {
const commentIndex = lineString.indexOf('#');
if (commentIndex > -1) { return lineString.substring(0, commentIndex); }
return lineString;
};

const lines = this.fileContents.split('\n');
for (let i = 0; i < lines.length; i += 1) {
const line = _stripComments(lines[i]);

const lineItems = line.replace(/\s+/g, ' ').trim().split(' ');

switch (lineItems[0].toLowerCase()) {
case 'o': // Start A New Model
this._parseObject(lineItems);
break;
case 'g': // Start a new polygon group
this._parseGroup(lineItems);
break;
case 'v': // Define a vertex for the current model
this._parseVertexCoords(lineItems);
break;
case 'vt': // Texture Coords
this._parseTextureCoords(lineItems);
break;
case 'vn': // Define a vertex normal for the current model
this._parseVertexNormal(lineItems);
break;
case 'l': // Define a line for the current model
this._parseLine(lineItems);
break;
case 's': // Smooth shading statement
this._parseSmoothShadingStatement(lineItems);
break;
case 'f': // Define a Face/Polygon
this._parsePolygon(lineItems);
break;
case 'mtllib': // Reference to a material library file (.mtl)
this._parseMtlLib(lineItems);
break;
case 'usemtl': // Sets the current material to be applied to polygons defined from this point forward
this._parseUseMtl(lineItems);
break;
}
}

return this.result;
}

_createNewModel(name = this.defaultModelName) {
return {
name,
vertices: [],
textureCoords: [],
vertexNormals: [],
faces: [],
lines: []
};
}

_currentModel() {
if (this.result.models.length == 0) {
const defaultModel = this._createNewModel();
this.result.models.push(defaultModel);
this.currentGroup = '';
this.smoothingGroup = 0;
}

return this.result.models[this.result.models.length - 1];
}

_parseObject(lineItems) {
const modelName = lineItems.length >= 2 ? lineItems[1] : this.defaultModelName;
const model = this._createNewModel(modelName);
this.result.models.push(model);
this.currentGroup = '';
this.smoothingGroup = 0;
}

_parseGroup(lineItems) {
if (lineItems.length != 2) { throw 'Group statements must have exactly 1 argument (eg. g group_1)'; }

this.currentGroup = lineItems[1];
}

_parseVertexCoords(lineItems) {
const x = lineItems.length >= 2 ? parseFloat(lineItems[1]) : 0.0;
const y = lineItems.length >= 3 ? parseFloat(lineItems[2]) : 0.0;
const z = lineItems.length >= 4 ? parseFloat(lineItems[3]) : 0.0;

this._currentModel().vertices.push({ x, y, z });
}

_parseTextureCoords(lineItems) {
const u = lineItems.length >= 2 ? parseFloat(lineItems[1]) : 0.0;
const v = lineItems.length >= 3 ? parseFloat(lineItems[2]) : 0.0;
const w = lineItems.length >= 4 ? parseFloat(lineItems[3]) : 0.0;

this._currentModel().textureCoords.push({ u, v, w });
}

_parseVertexNormal(lineItems) {
const x = lineItems.length >= 2 ? parseFloat(lineItems[1]) : 0.0;
const y = lineItems.length >= 3 ? parseFloat(lineItems[2]) : 0.0;
const z = lineItems.length >= 4 ? parseFloat(lineItems[3]) : 0.0;

this._currentModel().vertexNormals.push({ x, y, z });
}

_parseLine(lineItems) {
const totalVertices = (lineItems.length - 1);
if (totalVertices < 2) { throw (`Line statement has less than 2 vertices${this.filePath}${this.lineNumber}`); }

const line = [];

for (let i = 0; i < totalVertices; i += 1) {
const vertexString = lineItems[i + 1];
const vertexValues = vertexString.split('/');

if (vertexValues.length < 1 || vertexValues.length > 2) { throw (`Too many values (separated by /) for a single vertex${this.filePath}${this.lineNumber}`); }

let vertexIndex = 0;
let textureCoordsIndex = 0;
vertexIndex = parseInt(vertexValues[0]);
if (vertexValues.length > 1 && (vertexValues[1] != '')) { textureCoordsIndex = parseInt(vertexValues[1]); }

line.push({
vertexIndex,
textureCoordsIndex
});
}
this._currentModel().lines.push(line);
}

_parsePolygon(lineItems) {
const totalVertices = (lineItems.length - 1);
if (totalVertices < 3) { throw (`Face statement has less than 3 vertices${this.filePath}${this.lineNumber}`); }

const face = {
material: this.currentMaterial,
group: this.currentGroup,
smoothingGroup: this.smoothingGroup,
vertices: []
};

for (let i = 0; i < totalVertices; i += 1) {
const vertexString = lineItems[i + 1];
const vertexValues = vertexString.split('/');

if (vertexValues.length < 1 || vertexValues.length > 3) { throw (`Too many values (separated by /) for a single vertex${this.filePath}${this.lineNumber}`); }

let vertexIndex = 0;
let textureCoordsIndex = 0;
let vertexNormalIndex = 0;
vertexIndex = parseInt(vertexValues[0]);
if (vertexValues.length > 1 && (vertexValues[1] != '')) { textureCoordsIndex = parseInt(vertexValues[1]); }
if (vertexValues.length > 2) { vertexNormalIndex = parseInt(vertexValues[2]); }

if (vertexIndex == 0) { throw 'Faces uses invalid vertex index of 0'; }

// Negative vertex indices refer to the nth last defined vertex
// convert these to postive indices for simplicity
if (vertexIndex < 0) { vertexIndex = this._currentModel().vertices.length + 1 + vertexIndex; }

face.vertices.push({
vertexIndex,
textureCoordsIndex,
vertexNormalIndex
});
}
this._currentModel().faces.push(face);
}

_parseMtlLib(lineItems) {
if (lineItems.length >= 2) { this.result.materialLibraries.push(lineItems[1]); }
}

_parseUseMtl(lineItems) {
if (lineItems.length >= 2) { this.currentMaterial = lineItems[1]; }
}

_parseSmoothShadingStatement(lineItems) {
if (lineItems.length != 2) { throw 'Smoothing group statements must have exactly 1 argument (eg. s <number|off>)'; }

const groupNumber = (lineItems[1].toLowerCase() == 'off') ? 0 : parseInt(lineItems[1]);
this.smoothingGroup = groupNumber;
}
}

export default OBJFile;
Loading

0 comments on commit 1836c6f

Please sign in to comment.