Skip to content

Commit

Permalink
add lab 3
Browse files Browse the repository at this point in the history
  • Loading branch information
RyanQ96 committed Nov 2, 2023
1 parent 7700453 commit fa46e97
Show file tree
Hide file tree
Showing 15 changed files with 2,815 additions and 388 deletions.
1 change: 1 addition & 0 deletions 5542-codebase/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>RT-Rendering Lab</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gl-matrix/2.8.1/gl-matrix-min.js"></script>
</head>
<body>
<div id="app"></div>
Expand Down
4 changes: 2 additions & 2 deletions 5542-codebase/src/components/appbar/index.vue
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@

<script setup lang="ts">
import { ref, computed, watch } from "vue"
import { selectedShape, shapeIconMapping, selectedColor } from "@/core/setup-lab2"
import { selectedShape, shapeIconMapping, selectedColor } from "@/core/setup-lab3"
const iconShape = computed(() => {
return shapeIconMapping[selectedShape.value]
Expand All @@ -32,4 +32,4 @@ watch(() => selectedShape.value + selectedColor.value, () => {
transition-property: border;
transition-duration: 0.5s;
}
</style>@/core/setup-lab1@/core/setup-lab2
</style>
25 changes: 15 additions & 10 deletions 5542-codebase/src/components/webglCanvas/card.vue
Original file line number Diff line number Diff line change
@@ -1,16 +1,18 @@
<template>
<h1 style="padding-bottom: 10px; text-align: center; font-size: 2rem">{{globalMode ? "Global Mode" : "Local Mode"}}</h1>
<div ref="container" class="canvas-container">
<inner :width="width" :height="height"/>
<h1 style="padding-bottom: 10px; text-align: center; font-size: 2rem">Scene<v-btn class="indicator-btn" icon="mdi-eye"
style="background-color: transparant; " variant="text" @click="toggleFreeMode" :color="cameraFreeMode?'green': 'black'"></v-btn></h1>
<div ref="container" class="canvas-container">
<inner :width="width" :height="height" />
</div>
</template>

<script setup lang="ts">
import inner from './inner.vue';
import { ref, onMounted } from "vue"
import { globalMode } from "@/core/setup-lab2";
import { toggleCameraFreeMode, cameraFreeMode } from "@/core/drawwebgl-new";
// import { globalMode } from "@/core/setup-lab3";
const container = ref<HTMLElement | null>(null);
const width = ref<number>(1400);
const width = ref<number>(700);
const height = ref<number>(700);
const resizeObserver = new ResizeObserver(entries => {
Expand All @@ -19,23 +21,26 @@ const resizeObserver = new ResizeObserver(entries => {
height.value = entry.contentRect.height;
}
});
onMounted( () => {
function toggleFreeMode() {
toggleCameraFreeMode()
}
onMounted(() => {
resizeObserver.observe(container.value!);
})
</script>

<style scoped>
.canvas-container {
resize: both;
width: 1400px;
width: 700px;
height: 700px;
background-color: black;
overflow: hidden;
box-sizing: border-box;
margin: 0 auto;
box-shadow: rgba(0, 0, 0, 0.45) -7.5px 7.5px 10px !important;
box-shadow: rgba(0, 0, 0, 0.45) -7.5px 7.5px 10px !important;
border: 0.5px solid rgb(204, 204, 204);
}
</style>
11 changes: 6 additions & 5 deletions 5542-codebase/src/components/webglCanvas/inner.vue
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<script setup lang="ts">
import { ref, computed, onMounted, watch } from "vue";
import { bindMouseEvent, bindKeyDownEvent } from "@/core/setup-lab2";
import { bindCameraMouseControlEvent, bindKeyDownEvent } from "@/core/setup-lab3";
import { init } from "@/core/drawwebgl-new";
const props = defineProps({
width: {
Expand All @@ -28,14 +28,15 @@ const computedStyle = computed(() => {
const canvas = ref<HTMLCanvasElement | null>(null);
onMounted(() => {
const canvasComponent = canvas.value as HTMLCanvasElement;
bindMouseEvent(canvasComponent)
// bindMouseEvent(canvasComponent)
bindKeyDownEvent()
bindCameraMouseControlEvent()
init(canvasComponent)
})
watch(() => props.width + props.height, () => {
const canvasComponent = canvas.value as HTMLCanvasElement;
init(canvasComponent, false)
// const canvasComponent = canvas.value as HTMLCanvasElement;
// init(canvasComponent, false)
})
</script>
Expand All @@ -53,4 +54,4 @@ watch(() => props.width + props.height, () => {
position: absolute;
transform: translate(-50%, -50%);
}
</style>
</style>@/core/setup-lab3
263 changes: 263 additions & 0 deletions 5542-codebase/src/core/drawwebgl-new-lab2.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,263 @@
import { initFragmentShader, initVertexShader } from "@/utils/shaderUtils";
import { matmul, getInverseProjectionMatrix, getProjectionMatrix, getInverseRotateMatrix, getInverseScaleMatrix, matv } from "@/utils/matrix"
import type { TAllowedShape, TAllowedColor } from "./setup-lab3"
import { selectedShape, globalMode, colorMapping } from "./setup-lab3"
import type { TCoordSpaceLayout } from "@/utils/matrix"
import { globalInstance, Circle, Triangle, HorizentalLine, VerticalLine, Square, Point, HObj } from "@/utils/hierarchymodel"

// addShape, drawScene, init, clearCanvas

const canvasSpaceLayout: TCoordSpaceLayout = {
xMin: -700,
xMax: 700,
yMin: -350,
yMax: 350
}

const vertexShader = /* glsl */ `
precision lowp float;
attribute vec3 v3Position;
attribute vec4 v4InColor;
uniform mat4 ProjectMat;
uniform mat4 TransformMat;
varying vec4 v4OutColor;
void main() {
v4OutColor = v4InColor;
gl_Position = ProjectMat * TransformMat * vec4(v3Position, 1.0);
gl_PointSize = 10.0;
}
`

const fragmentShader = /* glsl */ `
precision mediump float;
varying vec4 v4OutColor;
void main() {
gl_FragColor = v4OutColor; // set all fragments to red
}
`

interface drawCommand {
shape: TAllowedShape,
offset: number,
count: number,
matrix: Float32Array
}

let canvas: HTMLCanvasElement;
let webgl: WebGLRenderingContext;
let fragmentShaderObject: WebGLShader;
let vertexShaderObject: WebGLShader;
let programObject: WebGLProgram;
let triangleBuffer: WebGLBuffer;
let jsArrayData: number[] = []
// let drawingCommands: drawCommand[] = []

let lastObjectOfInterest: HObj | null = null

export function enterGlobalMode() {
globalMode.value = true;
lastObjectOfInterest = globalInstance.objectOfInterest
globalInstance.setObjectOfInterest(null)
drawScene()
}

export function exitGlobalMode() {
globalMode.value = false;
globalInstance.setObjectOfInterest(lastObjectOfInterest)
drawScene()
}

export function detectCandidateObjectOfInterest(centerPoint: number[]) {
const mappedCenterPoint = htmlCoordToWebglCoord(centerPoint, [canvas.width, canvas.height], canvasSpaceLayout)
globalInstance.detectCandidateObjectOfInterest(mappedCenterPoint)
drawScene()
}

export function scaleUpObjectOfInterest() {
console.log(globalMode.value)
if (globalMode.value) {
globalInstance.scale(1.2, 1.2)
} else {
globalInstance.objectOfInterest?.scale(1.2, 1.2)
}
drawScene()
}

export function scaleDownObjectOfInterest() {
if (globalMode.value) {
globalInstance.scale(0.8, 0.8)
} else {
globalInstance.objectOfInterest?.scale(0.8, 0.8)
}
drawScene()
}

export function changeObjectOfInterestColor(color: TAllowedColor) {
if (!globalMode.value && globalInstance.objectOfInterest) {
(globalInstance.objectOfInterest as any).initializeData(colorMapping[color])
}
drawScene()
}

export function confirmObjectOfInterest() {
if (globalInstance.candidateObjectOfInterest) {
globalInstance.setObjectOfInterest(globalInstance.candidateObjectOfInterest)
globalInstance.candidateObjectOfInterest = null
selectedShape.value = globalInstance.objectOfInterest?.objectType as TAllowedShape
drawScene()
return true
}
return false
}

export function addShape(centerPoint: number[], shape: TAllowedShape, color: number[]) {
console.log("logging: addShape", centerPoint, shape, color)
const mappedCenterPoint = htmlCoordToWebglCoord(centerPoint, [canvas.width, canvas.height], canvasSpaceLayout)
globalInstance.objectOfInterest?.translate(mappedCenterPoint)
drawScene()
}

export function rotateShape(target: HObj, theta: number) {
target.rotate(theta)
drawScene()
}

export function rotateGlobal(theta: number) {
globalInstance.rotate(theta)
drawScene()
}


export function init(canvasEl: HTMLCanvasElement, reInit = true) {
canvas = canvasEl
if (reInit) initShape()
initWebGL()
initShader()
initProgram()
initBuffers()
drawScene()
}

export function clearCanvas() {
console.log("clearCanvas")
webgl.clearColor(0.0, 0.0, 0.0, 1.0);
webgl.clear(webgl.COLOR_BUFFER_BIT);
jsArrayData.length = 0
// drawingCommands.length = 0
}


function initWebGL() {
webgl = canvas.getContext('webgl') as WebGLRenderingContext;
if (!webgl) {
alert("Webgl is not available in your browser")
return
}
resizeCanvasToMatchDisplaySize(canvas);
webgl.viewport(0, 0, canvas.width, canvas.height);
webgl.clearColor(0.0, 0.0, 0.0, 1.0);
webgl.clear(webgl.COLOR_BUFFER_BIT);
console.log("init!")
}

function resizeCanvasToMatchDisplaySize(canvas: HTMLCanvasElement) {
canvas.width = canvas.clientWidth;
canvas.height = canvas.clientHeight;
webgl.viewport(0, 0, canvas.width, canvas.height);
}

function initShape() {
new Circle([-650, 300])
new Triangle([-550, 298])
new Square([-450, 300])
new HorizentalLine([-350, 300])
new VerticalLine([-250, 300])
new Point([-150, 300])
}

function initShader() {
vertexShaderObject = initVertexShader(vertexShader, webgl)!
fragmentShaderObject = initFragmentShader(fragmentShader, webgl)!
}

function initProgram() {
programObject = webgl.createProgram()!
webgl.attachShader(programObject, vertexShaderObject)
webgl.attachShader(programObject, fragmentShaderObject)
webgl.linkProgram(programObject)
webgl.useProgram(programObject)
}

function initBuffers() {
triangleBuffer = webgl.createBuffer()!
webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer)
webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array([]), webgl.STATIC_DRAW)
}

function updateDataBuffers(jsArrayData: number[]) {
webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer)
webgl.bufferData(webgl.ARRAY_BUFFER, new Float32Array(jsArrayData), webgl.STATIC_DRAW)
}

function getWebglShape(shape: TAllowedShape, webgl: WebGLRenderingContext) {
switch (shape) {
case "point":
return webgl.POINTS
case "triangle":
return webgl.TRIANGLES
case "square":
return webgl.TRIANGLE_FAN
case "vertical-line":
return webgl.LINES
case "horizontal-line":
return webgl.LINES
case "circle":
return webgl.TRIANGLE_FAN
default:
return webgl.POINTS
}
}


export function setShapeObjectsFromGlobal(shape: TAllowedShape) {
const candidates = globalInstance.children.filter(d => d.objectType === shape)
globalInstance.setObjectOfInterest(candidates[0])
drawScene()
}


export function drawScene() {
const {drawingData, drawingCommands} = globalInstance.render()
updateDataBuffers(drawingData)
const v3Position = webgl.getAttribLocation(programObject, "v3Position")
const v4InColorIndex = webgl.getAttribLocation(programObject, 'v4InColor')

const uProjectMat = webgl.getUniformLocation(programObject, "ProjectMat");
const ProjectMat = getProjectionMatrix(canvasSpaceLayout)
webgl.uniformMatrix4fv(uProjectMat, false, ProjectMat);

webgl.bindBuffer(webgl.ARRAY_BUFFER, triangleBuffer)
webgl.enableVertexAttribArray(v3Position)
webgl.vertexAttribPointer(v3Position, 3, webgl.FLOAT, false, 7 * Float32Array.BYTES_PER_ELEMENT, 0)
webgl.enableVertexAttribArray(v4InColorIndex)
webgl.vertexAttribPointer(v4InColorIndex, 4, webgl.FLOAT, false, 7 * Float32Array.BYTES_PER_ELEMENT, 3 * Float32Array.BYTES_PER_ELEMENT)
webgl.clearColor(0.0, 0.0, 0.0, 1.0);
webgl.clear(webgl.COLOR_BUFFER_BIT);

drawingCommands.forEach((command: drawCommand) => {
const uProjectMat = webgl.getUniformLocation(programObject, "TransformMat");
webgl.uniformMatrix4fv(uProjectMat, false, command.matrix);
webgl.drawArrays(getWebglShape(command.shape, webgl), command.offset, command.count);
})
}

function htmlCoordToWebglCoord(htmlCoord: number[], containerSize: number[], canvasSpaceLayout: TCoordSpaceLayout) {
const mappedX = htmlCoord[0] / containerSize[0] * 2 - 1
const mappedY = 1 - htmlCoord[1] / containerSize[1] * 2
const inverseProjectMat = getInverseProjectionMatrix(canvasSpaceLayout)
const inverseScaleMatrix = getInverseScaleMatrix(globalInstance.scaleTotal, globalInstance.scaleTotal)
const inverseRotateMatrix = getInverseRotateMatrix(globalInstance.rotateTotal)
const inverseTransformMat = matmul(inverseScaleMatrix, inverseRotateMatrix, inverseProjectMat)
// return [inverseTransformMat[0] * mappedX + inverseTransformMat[12], inverseTransformMat[5] * mappedY + inverseTransformMat[13]]
return Array.from(matv(inverseTransformMat, new Float32Array([mappedX, mappedY, 0, 1]))).slice(0, 2)
}
Loading

0 comments on commit fa46e97

Please sign in to comment.