Fakultas Ilmu Komputer UI

Commit 966ce3e5 authored by Rachmat Ridwan's avatar Rachmat Ridwan
Browse files

Implement highlighting selected object in WebGL

parent 59728a14
......@@ -7,7 +7,7 @@
height: 100%;
}
#screen-info {
top: 0;
top: 5px;
bottom: auto;
}
.menu {
......
......@@ -312,17 +312,21 @@ div#speed-slider {
position: absolute;
bottom: 0;
z-index: 1;
display: none;
color: white;
padding-bottom: 10px;
padding-left: 10px;
text-shadow: 0 0 8px rgba(0,0,0,0.3);
font-size: 14px;
letter-spacing: calc(3rem / 100);
color: #d7d7d7;
}
#canvas-status {
margin-bottom: 0;
display: none;
}
canvas:focus+#screen-info {
canvas:focus + * > #canvas-status {
display: block;
}
......@@ -349,6 +353,9 @@ canvas:focus+#screen-info {
font-weight: normal;
}
/* Tree */
#tree li {
position: relative;
}
......@@ -374,7 +381,7 @@ canvas:focus+#screen-info {
overflow-y: scroll;
padding: 11px;
margin: 10px 0;
background-color: #0000004d;
background-color: #131313;
}
li:not(.selected) > input[type="checkbox"]:hover + .obj-name {
......@@ -403,7 +410,7 @@ li:not(.selected) > input[type="checkbox"]:hover + .obj-name {
position: absolute;
content: "";
top: -5px;
left: 11px;
left: 12px;
height: calc(100% - 6px);
width: 1px;
border-left: 1px solid #a2a2a2;
......@@ -485,7 +492,51 @@ li.selected > ul > .collapsed-sign::before {
color: black;
}
ul > li:last-child::before {
content: "";
display: block;
position: absolute;
width: 10px;
height: calc(100% - 24px);
background-color: #131313;
top: 16px;
left: -17px;
}
#tree li > input[type="checkbox"]:checked + * + ul::after {
content: "";
display: block;
position: absolute;
width: 6px;
height: 6px;
border-radius: 10px;
background-color: #acacac;
top: -8px;
left: 10px;
}
.note {
font-size: 12px;
line-height: 1.2;
}
\ No newline at end of file
}
/* Selected object hierarchy */
#selobj-hierarchy > * {
display: inline-block;
margin-right: 0.5rem;
color: orange;
}
#selobj-hierarchy > *:not(:last-child)::after {
content: "\25B2";
color: white;
margin-left: 0.5rem;
transform: rotate(90deg);
display: inline-block;
}
#selobj-hierarchy > *:last-child {
font-weight: bold;
}
......@@ -16,6 +16,9 @@ uniform mat4 viewMatrix;
uniform mat4 projectionMatrix;
uniform vec4 lightPosition;
uniform float shininess;
uniform float selectingFactor;
void main()
{
// pos is vertex position in eye coordinates
......@@ -50,7 +53,14 @@ void main()
vec4 ambient = ambientProduct;
gl_Position = projectionMatrix * viewMatrix * modelMatrix * vPosition;
fColor = ambient + diffuse +specular;
fColor = (ambient + diffuse + specular);
float sel = selectingFactor;
// fColor = vec4(fColor.r * invSel, fColor.g * invSel, fColor.b * invSel, 0.0);
vec4 selectedColor = vec4(0.94, 0.64, 0.09, 1.0);
vec4 selMult = vec4(sel, sel, sel, 0.0);
vec4 invSelMult = vec4(1.0 - sel, 1.0 - sel, 1.0 - sel, 0.0);
fColor = fColor * invSelMult + selectedColor * selMult;
fColor.a = 1.0;
}
......@@ -104,6 +114,7 @@ main()
</canvas>
<div id="screen-info">
<p id="canvas-status">Canvas aktif dipilih</p>
<div>Objek dipilih: <span id="selobj-hierarchy"><span>body</span><span>black-body</span></span></div>
</div>
</div>
<div id="menu-toggler-wrapper" class="show-menu">
......
......@@ -362,18 +362,54 @@ function matchSlidersToAnimation() {
})
}
let currentSelection = ''
function deselect(modelName) {
let selectedElement = document.querySelector(`li[data-model-name="${modelName}"]`)
if (selectedElement) {
selectedElement.classList.remove('selected')
}
}
function replaceSelection(newSelection) {
let selectedElement = document.querySelector(`li[data-model-name="${currentSelection}"]`)
let newSelectedElement = document.querySelector(`li[data-model-name="${newSelection}"]`)
if (newSelectedElement) {
if (selectedElement) {
selectedElement.classList.remove('selected')
let currentSelection = sceneGraph.selectedNodeName
if (newSelection === currentSelection) {
deselect(currentSelection)
sceneGraph.selectedNodeName = ''
} else {
let newSelectedElement = document.querySelector(`li[data-model-name="${newSelection}"]`)
if (newSelectedElement) {
deselect(currentSelection)
newSelectedElement.classList.add('selected')
sceneGraph.selectedNodeName = newSelection
}
newSelectedElement.classList.add('selected')
currentSelection = newSelection
}
displaySelectionHierarchyText()
}
function displaySelectionHierarchyText() {
let hierarchyElem = document.querySelector('#selobj-hierarchy')
let child = hierarchyElem.lastElementChild
while (child) {
hierarchyElem.removeChild(child)
child = hierarchyElem.lastElementChild
}
let selectionModelName = sceneGraph.selectedNodeName
let selectionNode = sceneGraph.nodes[selectionModelName]
if (!selectionNode) {
return
}
let parentNameList = selectionNode.parentNameList
let hierarchyList = [...parentNameList, selectionModelName]
hierarchyList.forEach(modelName => {
let childElem = document.createElement('span')
childElem.innerHTML = modelName
hierarchyElem.appendChild(childElem)
})
}
function displayTree() {
......
......@@ -25,6 +25,16 @@ class ObjectNode {
return !!this.parent;
}
get parentNameList() {
let parents = []
let node = this
while (node.parent) {
node = node.parent
parents.push(node.key)
}
return parents
}
updateTransformations() {
this.model.updateMatrices();
this.children.forEach(children => {
......
......@@ -7,7 +7,7 @@ class Renderer {
static recursivelyRenderNodes(node, sceneGraph) {
let gl = sceneGraph.gl;
Renderer.renderModel(node.model, gl, sceneGraph.glLocations);
Renderer.renderModel(node.model, gl, sceneGraph.glLocations, sceneGraph);
// Traverse the whole tree and render every visited node
......@@ -26,7 +26,9 @@ class Renderer {
* to avoid calling `flatten()` every time an object is rendered.
*/
static renderModel(model, gl, glLocations) {
static renderModel(model, gl, glLocations, sceneGraph) {
let selected = sceneGraph.selectedNodeName === model.name;
const {
ambientProduct,
diffuseProduct,
......@@ -44,6 +46,13 @@ class Renderer {
false,
flatten(model.fullTransformMatrix)
);
if (selected) {
gl.uniform1f(glLocations.selectingFactor, 1.0);
}
gl.drawArrays(gl.TRIANGLES, model.bufferStartIndex, model.vertexCount);
if (selected) {
gl.uniform1f(glLocations.selectingFactor, 0.0);
}
}
}
\ No newline at end of file
......@@ -13,6 +13,8 @@ class SceneGraph {
this.pointsArray = []
this.normalsArray = []
this.selectedNodeName = ''
/**
* List of materials in dictionary-style.
* Every material object has Phong parameters
......@@ -172,6 +174,8 @@ class SceneGraph {
locations.modelMatrix = gl.getUniformLocation(program, "modelMatrix")
locations.viewMatrix = gl.getUniformLocation(program, "viewMatrix")
locations.projectionMatrix = gl.getUniformLocation(program, "projectionMatrix")
locations.selectingFactor = gl.getUniformLocation(program, "selectingFactor")
gl.uniform1f(locations.selectingFactor, 0.0)
gl.locations = locations
......
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment