Red Shelf Documentation

P. K. Kelkar Library
Courtesy: P. K. Kelkar Library

This project will involve creating a 3D catalog of the library, which will include a search engine for the library. Users will be able to visit the website and search for a book, and the system will show the exact location of the book on the library racks. This project will require the use of Three.js and JavaScript. I may also explore database management and use SQL to improve the website’s performance.

Interactive 3D Book Locator for P. K. Kelkar Library, IIT Kanpur The Red Shelf is a web-based library navigation system designed to help users quickly locate physical books inside the large and complex layout of the P. K. Kelkar Library. Instead of relying only on shelf codes or floor numbers, the system provides a visual, spatial wayfinding experience using an interactive 3D model of the library. Users search for a book by title, author, or identifier through a simple search interface. The backend queries catalog data and maps the book to its corresponding physical bookshelf. The frontend then displays a 3D model of the library, where the target bookshelf is dynamically highlighted in red, allowing users to visually understand the exact location of the book. This makes physical navigation faster, especially for new users and large collections. The system is built using Three.js for real-time 3D visualization and Blender for modeling the library layout and shelves. A Node.js + Express backend handles search requests and data flow, while PostgreSQL is used to maintain a relational mapping between books and their physical shelf locations. The project is designed to integrate with the institute’s existing library catalog infrastructure and is optimized for use on mobile devices as well as desktops. The Red Shelf focuses on clarity, usability, and performance rather than visual excess, ensuring that the experience remains lightweight and accessible. The project demonstrates the application of full-stack web development, database design, and 3D visualization to solve a real, campus-scale problem and is intended to be handed over as a functional tool for institutional use.


Phases of this project

This project will be excuted in three phases. And they are as follows:

  1. Modelling: I will have to build the model of this library, an dfor this I will first take many pictures of my own library. After whcih i will make the model in bledner. I will also take the pictures of my shelfs and there IDs. Names of the model in blender has to given carefully. FOr this phases I am giving myself three days. One day to get the refrences and setting up the idea, and the rest two days to model the whole library. This is schedules to be executed on 16th January to 18th January. Link to the final blender file is given here :

    Download (16.3MB)

  2. Front-End : This will not be the for the first time that i will be used thre js to make this. The Front-End of the website will be kept minimal. I will add the search bar where I will be aksing for the ID of each book. And thats it. So all that the front end will contain is the Search bar, and Library model, and also space for the title of this project. Along with the footer with links to this documentation, code, and also link to my personal website, damn it!
  3. Back-End : This will be the tough part. The backend will be made in node.js and also PostgreSQl. node js tp send the query to databse, and PostgreSQl to retrieve the data from the database. This will be my first expereice with Database.
    Once the location of the bookshelf is retirved, I will remove the search bar, make the library's opacity very low, and the bookshelf inside it will be made to appear somewhat dim, and then the bookshelf where you would find the book will be turned Red. Hence the name Red Shelf.


Phase 1: Modelling

16/1/26

I have just now came taking some pictures of the library. And the link to all the pictures of library is given below. And after seeing the library closely, which I haven't done even though I have visited it multiple times, I see that it's architecture is magnificent. The complexity, and unsymmetricity in the desing makes me wonder how could some one even imagine this. The architect of our library is Achyut Kanvinde. I don't have words to describe how great his work is. Truly Amaaazing a work and an Amaaazing Architect! I have linked all the downloadable pictures of the library that I will be using as reference, below.

Download (1.52GB)

From tommorrow onwards, I will start modelling the library. So the plan it to make the model as low poly as possilbe, and visit the library later on perfecting the model with small details. But I dont aim to have a perfect model ready by tomorrow.


17/1/26

Ok so today, I got wasted. I am feeling very low from the start of this day. nothing seems to be working out. I am feeling very low. This might be the lowest poitn in my life. But I don't want to make this documentation a personal diary. So I will meet you tomorrow. And whether or not I start modelling will depend on my mood tomorrow.

Ok, so I tried making the library and I had gotten everything right, and as soon as the adrenaline rushed, my file got deleted due to Blender crashing. I got fucked up. This was very annoying. Hours of work got deleted instantly. I had almost completely made the entire outer part of the library before it fucked me.

Ok, so I put some more time in and made the model again. Now here are the results. As I proceed with the modeling, it becomes more and more easier, and more and more interesting. I have made more than what I expected. Here are the images.



18/1/26

I am completely satisfied by today’s work. I have successfully made almost the entire exterior of our library, and now is the time when I will be building the interior, since that is why this application will be used. So today, I have completed the exterior except for the handles for the stairs and the staircase at the other side of the library. And apart from that, everything is done, along with the first implementation of Three.js. So with that, I will show some of the results that I have done today. I have also added an opening animation to make it look good, but haven’t added the search bar and the footer. I will be adding that in the next schedule.

Blender file




The Website (First Appearance)



So today, now that I have completely made the model and its website, next week I will work on perfecting the model and also working on the front end. So the task that is left is to make the frontend, which includes making the search bar and the footer, and also fixing the animation of the opening page of the website. And then the most important part is to name the shelves of the website. And then one thing I am thinking to do is use GSAP and make the user experience the interior of the library too. And this will give them an immersive experience to travel to the bookshelf. I will make the interior as minimal as possible.

So here is the flow. The user will click a start button and then he will see the website starting along with the animation. And then he will see the search bar, where he will put the ID of the book. And then after phase three of the project is completed, the user will see the bookshelf of that book turning red. So after that, the user has the option to use the GSAP method and actually travel along the path through the interior to get to the bookshelf. And once he clicks the first “flag,” he will be locked in the position of the camera, but he can rotate. And then he will click the next flag, and likewise he can travel to the bookshelf. So when he is locked in the GSAP, he will be allowed to go back to the normal view (global orbital), and during the GSAP mode, he will not be able to change the location of the camera, only the rotation. This will not allow the user to move into the mesh.


19/1/26

So today,I have added the search bar which will take in the ID of the book, and have also added the footer, the headign of the app. GIven below is the picture of the application. I also fixed the footer to become responsive.


21/1/26

I have done a lot of work today. I successfully animated the camera using GSAP. I added red-colored location icons, and when they are clicked, the camera animates to those locations, allowing the user to explore the library from the inside. My aim is to build on this and allow the user to navigate all the way to the final bookshelf they are looking for. The GitHub repository has also been updated, and the application is now live. The app is hosted on Vercel. I usually host all frontend websites on Vercel and use Render for the backend—just a recommendation.


26/1/26

AA lot of work has been done in these five days and I am going to explain them one by one. The first and major feature is the search. I have successfully added the search feature into the application, wherein now it is possible to search for a bookshelf, and for a dummy shelf system I have numbered them from 1 to 36.

So the way this is done is I have named the bookshelf such that it matches their actual names that will be used to make their color red in Three.js. And then when the search button is clicked, I make the bookshelf which was entered by the user red. The user will enter any number from 1 to 36, and so as soon as it submits the form, the bookshelf will be turned red, and also I make the whole library translucent. Now one issue I was getting was that even if the opacity was turning down, it was not making the mesh behind it visible. I was still unable to see the bookshelf behind the walls, and so I added these two lines.


            if (child.isMesh && child.name == 'Cube041') {
                child.material.transparent = true;
                
                gsap.to(
                    child.material,
                    {
                        opacity : 0.5,
                        duration : 1,
                        onComplete : ()=>{
                            child.material.depthTest = true;
                            child.material.depthWrite = false;
                        }
                    }
                )
            }
                
And it worked. Given below is the image of the library turning its opacity down, and the searched bookshelf (2) is clearly visible.

Another feature added was the use of Geometry Instancing. I thought this would not be required since there are no trees or models that need to be scattered, but then I quickly realised there are cycles. I had modelled each and every cycle initially, but then the size of the file reached 38 MB (>25 MB). So in order to bring it to 25 MB, I created a JSON file storing all the transformations of the instances of the cycle in it, and then used it to create the instance of the cycle in Three.js, saving me the memory of creating all the cycles individually. This has brought the size of the GLB file to 7 MB, which was a huge achievement. I later used geometry instancing in the cycle stand and air conditioner as well to save some memory. But this was before realising that instancing the cycle itself had brought the mesh size well below 25 MB.


Another feature I have added is that now the user could actually navigate itself to the bookshelf, and for that I used the GSAP locations placed inside the library to guide the user. I still had the feeling that this might be too complicated, since the user might not have much patience to tap onto each of the points and so on. But I will take a look at it some other time. Here are the pictures of me navigating myself to some bookshelf.


Another feature that is added is the refresh button. So now that I have added the search, going into the GSAP mode and coming back, I don’t want there to be the search button, since there is already a book to be found. And also I don’t want the user to not have the option to search another book. Actually, I could have kept the search visible, but that would mean that the library could never come back to its opaque state after the first search was made, since every time the user comes back from the GSAP mode, it will make the library translucent. And since translucent would mean more parts of the mesh have to be rendered, this actually makes the application slower. Considering that this also has to be run on smaller devices, I had no other option but to give the chance for the application to again show the opaque library. But I will think about this problem.

And then finally, I would like to say that I have used the GSAP library a lot this time. Whether it is to change the opacity of the library, camera movement, or the movement of other HTML elements, all are animated using GSAP, which has made the work easier.

And lastly, I have seen that having the controls with damping, made the application slower. And my experience with the three.js editor said me that it is better to have the orbital controls with no damping. And thus I disabled the damping.

                    
            //Reset the Controls
            //controls.enableDamping = true;
            //controls.dampingFactor = 0.05;
            controls.screenSpacePanning = false;
            controls.enablePan = false;
            controls.minDistance = 0;
            controls.maxDistance = 900;
            controls.maxPolarAngle = Math.PI / 2;
                    
                

And now the controls might seem to be sudden, but it has definitely saved the application from lagging to some extend.


29/1/26

So the task for today is to make the camera face the right side. So the thing is, when a user clicks a GSAP location, he should be facing the next GSAP location. And this is the aim for today. I will have to change the location of the camera such that it faces the next GSAP when aiming at the target. Which means to play with the offset. The way I have done this is given in the following example:


            if (selectedObject.name == "GSAP1") {
                //console.log("Do what you want to with GSAP1");
                animate_Selection(selectedObject, 18, -0.5, 1);
            }
                    
This is one of such functions. So this function will make the camera move to the GSAP1 if it is selected. And the arguments that are passed to this function, i.e., 18, -0.5, 1, are the location of the camera w.r.t. the origin of the GSAP. In Blender, I have set the origin of these objects on the ground, much below the mesh, touching the ground. This will make scaling the GSAP look as if they are appearing from the ground. And having the z location equal to 18 will allow the camera to be above the origin, since I want the height of the camera to match the height of the eyes of a human. And the numbers -0.5 and 1 are the X and Y offset from the target, which I will be controlling for each GSAP now.

I wish to make the loading page and the complete first floor today. This will increase the vertex count, and for that I will aim to make just the library transparent but not the rest of the assets, since that will make the app very slow otherwise.


3/2/26

So today, and also some days ago, I have made even more responsive. And this time the icon of the app will change into the text when using ont he desktop and it changes into the icon when using on phone. media query is used to attain such response from the website. When I had the meeting last time, i was said to have some more feature. And here is the next step that i thought the website should implement. And that is to have a real time location indicatior, just like in the game of GTA. And the second thing to have is the percentage bar which tells the user how much percent of route he has covered. Lets keep it till there for now. And i will think about the rest of the feature later.

So the feature will be as follows. The user enters the location of the bookshelf, and then when it enables this 2D map feature, he/she will be able to see the projection of the library from the top view, and along with that he/she will see the red location like those rings of lights as in GTA, and this will also be reflected on the 2D map. And as the user reaches those points, he/she will be able to see the red point disappearing. This is very close to VR tech. Hopefully it works out.

As of now here are the updates:

The app's icon/heading is now responsive, and can respond to the device that it is used in.
The options Menu


18/2/26

After a long time I have returned and added three major features in the app. One of them is still not complete. So the features (as I call them) are:

  1. Geo Location
  2. Percentage Bar
  3. Frustum Pop Ups
I understood many things in Three.js by implementing the Frustum and Geo-location. And I am going to discuss all that I have learnt in this part of the documentation.

1. Geo-Location :
This feature is like Google Maps, where the user will be able to see from the top where he is and where he has to go. This will allow the user to visually see where he is with respect to the nearby GSAP. But for now, I have seen that from the desktop where I am developing this app, the accuracy of the browser is about 186m, which is huge. But nevertheless, I will still implement this feature and see how useful it turns out to be. The figure below shows how the position coordinates are seen on the console using the Geolocation API.

2. Percentage Bar : This feature was not very hard, comparatively speaking. And this is inspired by how we all appeal to visuals of our progress. Be it a loading screen or any task that wants us to see how much we have done. So this idea came from that. This is somewhat hard coded till GSAP9, which is at the entrance of the front gate. The figure below shows how the progress bar changes its scale from 0 to 100% as the user moves to the respective bookshelf. After pressing the back button, the scale exactly turns to zero, and for the first GSAP it turns to 1%.





3. Frustum :
This is one of the coolest features I have found in Three.js. Frustum is the feature that could be used to see which object is completely in the screen. This allows me to use the coordinates of the object and project it onto the 2D screen, and then position the frustum pop up at the same location, giving the illusion that the pop up is actually attached to that object. This has to be one of the most important features in Three.js. Given below is the picture of the frustum working as expected.


22/2/26

Lately, I was thinking about some other ideas related to the website. I will now be listing them.

The first plan is to use geometry instancing and make the bookshelves as instances. This will allow me to use the advantage of having a lesser number of meshes, and this will surely make the app faster and also give me the ability to change the properties of the mesh on the go. Also, with the help of Geometry Instancing, I will be able to make the target bookshelf more detailed, letting the user know in which row or which side of the shelf they can find the book.

And then the next thing to work on is adding a way to change the location of the bookshelf by the staff. That will make it easier for the admin to change the location of the bookshelf, change the name of the bookshelf, or just add or remove a bookshelf. Thinking about this, all that I have to do is give the admin the ability to change the JSON file that stores all the transforms.

And lastly, I have to say that adding the feature of Frustum was great, and I will surely add this feature of frustum extensively throughout the library. I have also thought of adding images of the library entrance to make it easier for the user to navigate themselves at the entrance of the library. Important locations like the dustbins and washrooms can also be marked, by red color if needed.

I am currently working on adding the bouncy pop-up feature, which will allow the user to see what’s the next pop-up to click from their current location. And I am also working on a cartoon version of the library, maybe to change the theme of the app. And for this, I am thinking of going with Grease Pencil in Blender.


23/2/26

I have been seeing the reaction of the people when they use this app, and I have seen that they find it interesting, but with that I have also seen a common pattern in the users. After reaching the bookshelf, they tend to click the red shelf. And this means that something must happen when the user clicks the bookshelf. And then some said that the library must be colored. And some found it hard to find the search bar. Also, some found it hard to click on the Entrance GSAP.

That’s it for now. I have an exam tomorrow and all the above problems will be solved by tomorrow, after the exam.

So here is the game plan.

Date Description
24/2/26 (Day)
  • Extensive Frustum all over the library
  • Entrance GSAP Frustum
  • Bouncy Next GSAP
  • Search Bar Design
  • Bookshelf Pop Up
24/2/26 (Night)
  • Library Color and Grease Pencil Sketch


26/2/26

It’s 5 AM and I haven’t slept. Since yesterday, I’ve been continuously working on adding feature after feature, and there has finally been huge progress that I would like to share. Below is the list of updates that I am going to discuss:

  1. Added colors to the mesh
  2. Entrance Frustum Pop up
  3. Developed the model even more.
  4. Added Some more additional Frustum
  5. Bouncing Next GSAP animation
  6. Oultine Feature
Now lets go about each of them one by one.

Added Colors to the Mesh :
It took me about three hours. I started adding different coloring materials in the scene. The materials were added to the library to make it look more accurate. And not just the color, but I also tried replicating the roughness of the mesh as much as possible. Given below is the model in Blender. You can see the dustbins and the glass materials, where the attribute of roughness being changed is clearly visible. Shade Smooth was applied to the dustbin and the cycle stand to make them look smoother rather than more like polygons.

Image of Cycle Stand in Blender Image of Cycle Stand in Three.js

Image of Dustbin in Blender Image of Dustbin in Three.js

Image of Fence in Blender Image of Fence in Three.js

For some reason, I am able to see the shine on the dustbin, cycle stand, and also the fence at the front of the library, but I am unable to see the shine of the glass window when I import the model into Three.js as a GLB file.
Image of Glass in Blender Image of Glass in Three.js

And finally, here is the complete colored model in Blender and in Three.js (Red Shelf).
Image of model in Blender Image of model in Three.js

There was also a strange problem I faced. When joining two objects into one single mesh in Blender, if both objects had different materials, I noticed that the joined mesh becomes a group, and the individual children of the group become separate objects with just one specific material. Also, the names of the children are randomly assigned. I do not understand why this happens. I have somehow handled this in the code. Wherever I am required to work with the mesh of the complete library (which contains individual child meshes with particular colors), I use every child of the library to handle the logic.

Entrance Frustum Pop Up
In here I have used the concept of frustum and created an entrance frustum that makes it easier for the user to understand where to start. I understand that even though the model is made to replicate the actual library as much as possible, it is still possible that the user might be unable to find themselves inside the app. So for that, I have added these entrance pop-ups with actual pictures of those locations. This allows the user to understand exactly where to begin.

While making this, I realized that having all four pop-ups appear at the same time would make it messy. So I used the coordinates of the camera to determine which side of the library the user is currently viewing. The Z-coordinate of the camera (which divides the library into two halves) decides which pop-ups should be shown. If the Z-coordinate is positive or negative, it determines whether the pop-ups on this side or the opposite side should be displayed.

image of the pop ups from one side image of the pop ups from the other side

I also realized that if the pop-up is too large, it can cover almost the entire screen, especially on smaller devices. To handle this, I controlled the size of the pop-up depending on the zoom level of the camera. When fully zoomed in, the scale of the pop-up increases up to 1.5, and when completely zoomed out, it scales down to zero. The scale is then linearly interpolated for any given distance of the camera from the orbital controls target. I have also added he event listeners ont he pop up, so if the entrance pop isd very small, one can also click on the pop upmto go that respective GSAP.
image of the pop up being small image of the pop up being big when zoomed

The origin of the scaling is also checked to prevent the pop-up from deviating from its location due to scaling offset. Similarly, additional adjustments were made to ensure the pop-up remains visually stable and aligned during interaction.

Developed Mesh :
I have also developed the mesh connecting the first floor to the second floor and down to the ground floor. On the ground floor, I added the washroom section, the kiosk machine, and the reading room. For the tables, I used instancing.

Ground floor with washroom in Blender Ground floor reading room in Blender
Ground floor reading room in Three.js

Similarly, for the first floor, I used geometry instancing to create the tables. The glass door near the washroom side of the first floor has also been modeled. Both of them could be seen in the image beow
Image of the glass door

Finally, the second floor has also been created — not with many details yet, but enough to make it presentable.
Image of me beig at the second floormage of me beig at the second floor
Initially, I had IDs ranging from 1 to 62 to guide users to the bookshelves on the first floor. To allow exploration of the ground floor and the second floor, I added ID 63 for the reading room on the ground floor and ID 64 for the second floor. These are temporary IDs used for testing the application.

Additional Frustum :
This is not the beginning. I am planning to add even more frustums along the way so that everything can be clearly defined and nothing remains under the hood. I have added the following frustums just to demonstrate the potential of this feature.

image of the first set of frustum

image of second set of frustum

image of the third set of frustum

I would also like to note that this frustum feature sometimes fails on mobile phones but works completely fine on desktop. It might happen that the GSAP at the entrance of the library and the first one inside the library disconnect from each other (no back-and-forth traveling possible) when the frustum is turned on on a smartphone. However, this issue does not occur on desktop.

Bouncy Next GSAP
This still requires some refinement, but it is working. It makes the NEXT GSAP bounce according to the ID entered, indicating which pop-up the user needs to click. This took quite a bit of time to implement, but in the code section, I will explain how I finally managed to do it. Here, I learned about gsap.killTweensOf(div), which stops the GSAP animation that was previously applied. It is quite useful.
With this, I also realized that it is not necessary to explicitly tell the user to click the GSAP. The entrance GSAP will naturally be clicked since the pop-ups are visible. However, to help the user identify the next GSAP, making it bouncy should be sufficient. I do not think anything more needs to be added to this feature in the future.
Now to make this, I have actually mapped all the GSAP and have programmed the route, could be considered as hard coded. Given below is the image of the map

map of the next gsap

Outline Feature :
This has to be one of the best things that happened while developing Red Shelf. I am using the outline function in Three.js, which creates a mesh outline through post-processing. Along with the added colors, it has made the app extremely beautiful, I would say. However, with the added benefit of the outline, I also noticed that it significantly slows down the application. Because of this, I initially disabled the outline feature and instead provided an option to enable it. If a user feels their system has enough power to run the app smoothly without lag, they can turn it on. Shown below are some images of the library with the outline enabled.




27/02/2026

So fimaly today, I was able to put some important features in the app. I will discuss about each of these feature. Here is the list of features that were implemented today.

  1. Complete Instacing of the bookshelfs
  2. Introduction of Target Bookshelf
  3. Availability of Seats in the library
Although they might not be large in number but each one of them has a hugh impact on the performance and usabilty of the app.


This is what took a large portion of my time. Here, I converted the bookshelves into instances, which significantly reduced the memory required to store them. One major advantage of this approach is that since I am no longer storing separate meshes, I can introduce more detailed geometry without worrying too much about the overall file size. I also redeveloped the entire logic that I had previously written for the meshed bookshelves, but this time adapted it for instancing. This gave me a significant advantage in terms of performance and flexibility. The file size reduced from 9.8 MB to 9.2 MB, which is a positive indication of optimization. Below is an example of a shelf turning red, similar to how it behaved in the meshed case. I would like to emphasize again that these are not individual meshes but instances of a single mesh, and their behavior is controlled using the instance index. Additionally, along the way, I realized that it would be visually better to keep the other bookshelves in yellow.
image of bookshelf in blender image of booklshefs turning red and yellow image of the ipad with maps of index


As mentioned earlier, converting the bookshelves into instances saved storage. Because of that, I was able to create a more detailed bookshelf model specifically for locating books, with full access to all the racks inside it. This allows the user to navigate to a specific section of the bookshelf. This detailed bookshelf is an actual mesh. Its position is set based on the corresponding instance at that location. When the user navigates to a bookshelf using GSAP, the instance at that position scales down, and the detailed mesh (the target bookshelf) is moved to the exact position of that instance. When exiting GSAP mode, the instance is scaled back up and the detailed bookshelf is scaled down. Below is the detailed bookshelf view.
Image of the bookshelf at the start Image of the detailed bookshelf after exiting GSAP Image of the bookshelf at the end
I also added additional GSAP positions at each bookshelf location so that the user can move as close to the shelf as possible. Since there are 62 bookshelves, there are enough GSAP points to provide a complete close-up view of each one.
Image of all GSAP points on the first floor in Blender
All GSAP points are scaled down except for the one mapped to the selected bookshelf. These newly created GSAP points for the target bookshelf are what I refer to as target GSAP.

Availability of Seats in the Library :
Finally, a feature that I consider just as important as finding a book — checking seat occupancy in the library. If the data is provided accurately, the application can now display which tables are empty and which are occupied. This is implemented by controlling the color of each instance, which makes it a practical feature, especially during exam periods. Below are images showing the tables before enabling seat occupancy, followed by views of the feature enabled in the reading room and on the first floor. I also added one more GSAP point in the reading room to provide a better view of the tables. The table with green color are those that are vacant and those with red are occupied.

Image of seats without seat occupancy enabled first floor Image of seats with seat occupancy enabled on the first floor Image of seats without seat occupancy enabled ground Image of seats with seat occupancy enabled on the ground floor Image of seats with seat occupancy complete


1/3/2026

So, some other cool features have been added to the app to make it more useful. I will first list the features below and then discuss each of them in detail.

  1. Direct access to any GSAP using the percentage bar
  2. 2D floor overview of any floor in the library

Direct GSAP access using the percentage bar :
Here, I have added GSAP icons on the percentage bar that allow the user to directly go to a specific GSAP. This comes from the understanding that a user might not have time to go to each location one by one, especially if they are already familiar with the structure of the library. Therefore, I added these GSAP icons for quick access.One problem I am finding hard to solve is how to animate the path instead of directly making the camera move in a straight line from one GSAP to another through the mesh. Below is the image showing these GSAP icons on the percentage bar. I will explain how I implemented this feature in the code explanation. I am using class names to handle the creation of these icons and also adding event listeners to them.

image of percentage bar with the GSAP icon

2D floor overview of any floor in the library :
My aim here was to give the user a quick overview of the path they need to take in order to reach the target. To do this, I created a new option called "Floor," which allows the user to view the library and its floors from the top. This feature can be used to find the path from a top-down perspective and also to see the total number of rooms, their purpose, and the occupied tables — all from above. This can be done for each floor, right from the basement to the second floor.

image of the floor option image of the floor option image of ground floor image of first floor image of second floor
I have decided to use this feature instead of reducing the opacity of the library to zero. Using opacity on the library is not performance-friendly. Also, I do not think the reduced opacity clearly shows the target location. In comparison, the floor cross-section view clearly displays the target and makes the location much easier to understand.

Now, here are some other features I have in mind:

  1. Location Sharing : A user could share the location of a table or a bookshelf with others through the app. The user could go to the app and then to the floor section. From there, they could place a GSAP icon at a specific location (for which I will use the Three.js example of dragging and moving an object) and then share that location with another user. The other user will see the icon moving on their phone in real time. This feature could be quite useful. Thanks for the idea, Aseem!
  2. Game : A game where the user has to guess the book and the shelf where it is located. Depending on how close they are to the target bookshelf, they will be rewarded. This is inspired by a game I saw where the user has to guess a location based on a picture of a street or a place, and depending on how geographically close their guess is, they are awarded points. However, this is not really a core feature, but rather a possibly unnecessary way to make the app more engaging.


2/3/26

So today I didnt do much. Just fixed the color. And minor chnages in the app.

I made the color of the library a bit more light and bright. For some reason, I felt that the colors of the library were dull. And just to increase the brightness of the library, I have made the color grade of the app lighter. Secondly, I have changed the flow of the app. Now, after submitting the ID, I will make the particular floor of the library visible where the book lies. And then the rest of the floor will be scaled down. This is, I think, much better than the opacity setting that I had initially made. Given below are the colors of the library now after making some changes.


3/3/26 (Version 2)

So this is going to be great. I had a meetign with some staff memebers of library, and they are now going to provide me with the data about the bookshelfs. Adftr which I can start filling the data. But meanwhile I have got another great idea. in the talk today, they have asked me if it is possible for the app to provided a way for the user to select the position where he is located at the moment which is the current location. And then select the destination location. And the app must be able to find the optimal path to reach there. This is going to fucking strech the graph searhc muscle. Amazing. There are few options. But I have decided to go with A* Algorithm and the reason is I have got an exellent tutorial that explains me about this algorithm. Here it is.


3/3/26

I have decided that it is no longer necessary for the navigation to begin strictly from the entrance. This marks a significant shift in the overall plan. Instead of assuming a fixed starting point, I will allow the user to choose both the starting and ending locations within the library. To support this, I have distributed several GSAP interaction points at different locations throughout the application. The updated workflow will proceed as follows:

The user will first select the floor from which they wish to start (for example, the Ground Floor). Once selected, the application will enter a dedicated navigation selection mode. In this mode, the frustum view will activate specifically for start-point selection. Unlike the normal interaction mode, this view will not display pop-ups for physical items such as books or shelves. Instead, it will present images representing the surrounding area of each selectable location. After the user selects and confirms the starting point, the same process will be repeated for selecting the destination (ending location).

Once a floor is selected, its cross-sectional top view will be displayed. A navigation grid will then be overlaid on the floor plan. The nodes of the grid will be represented as reddish-black circles connected by black edges. When the user selects a node, a confirmation pop-up will appear displaying images of that location. Upon confirmation, the selected node will be marked as the starting point. The user will then select the destination node, which will be displayed using a different visual style (for example, black circles with straight connecting lines).

After both the starting and ending nodes are selected, the A* algorithm will be executed to compute the shortest path. The resulting path will be visually highlighted on the map, and the corresponding GSAP markers along the route will scale up to indicate the navigation path. If the user selects any of the location pop-ups, the application will transition back into the normal GSAP interaction mode, and the app will continue functioning as usual.

Implementing this change will require significant restructuring of the existing codebase. The previous concept of fixed entrance pop-ups will be removed, and the navigation logic will be refactored into a more flexible and modular system.


4/3/26

Today, I have achieved a big milestone. And it is that I am successfully able to implement the Dijkstra Algorithm, and this is the one which guarantees the path with minimum distance. I started making this algorithm yesterday, where I formed the graph with proper nomenclature, and the image of the same could be seen below :

This is where I first named the GSAP, Nodes, and Edges of my graph. And later I named the objects in the Blender the same way. And finally I also made the array of objects with the same nomenclature, the image of which is shown below

And finally I implemented the code for the A* algorithm. From what I have learnt from the video, I see that A* is an improvement of Dijkstra Algorithm. A* algorithm is what takes the advantage of directionality of Greedy Search and the optimality of Dijkstra Algorithm. But in my case there is a bit of a problem with the greedy algorithm, and that is the existence of floors and stairs. Let me explain it from the below diagram.

So the A*, which I assume to be the combination of Dijkstra and greedy, works well and very effectively in the case of geographical maps. This is because there are no maps or worlds lying above another world. But in the case of the library, the geographical location of the nodes of the graph can also lie on top of each other (for example on the ground and first floor), and this means the physical distance between two nodes that are on top of each other (one on first and the other on ground floor for example) may have a very small physical distance, but there might be some other point on the ground floor that may not be that close to that target node on the first floor, but will surely take less time to reach the point on the first floor than the other. And this is because one point on the first floor will be closer to the stairs or lift than the other. So this means if we were to use the greedy search approach, we will first have to solve for the ground floor with the target being the stairs, and then have to solve for the first floor with the target being the original target but the starting point being the stairs. This might still look good, but the problem comes when there are more than one way to go to the next floor, and both of which contain different amounts of effort to move from one floor to another. Lifts and stairs. I will look after that problem later, but for now I haven’t dealt with the complication of distance between the current location and the target location (heuristics / Greedy Search Algorithm), and have stuck to Dijkstra Algorithm which does have the disadvantage of uniformity in its search, but for a small graph like in this case, I believe it doesn’t matter.

Apart from the Search Algorithm, I have also thought of re-designing the UI/UX of the application. The flow of the application specifically. And a mental map of the same is given below.


7/3/26

This must be the second time I am fucked up making this application. Yesterday, I mistakenly over written my entire code with what I was programming a day before yesterday. Meaning I lost all the code that I had written yesterday. And believe me, these three days I have been re-developing the whole application. It is fuckingly annoying. Whoever made the feature to overwrite the code in VS Code should be punished. No disclaimer pop up before overwriting, nothing. Bloody idiot.

Anyways, I have been working on making the "application flow" or the UI design of the application. And the map below shows how the application will proceed. This is the map of the UI of the application (rough idea), and it also shows what each button would do in the application.


I have been working on the code in JS since the last three days. But due to that foolish carelessness yesterday, I lost my code yesterday. But the good thing is that I did not lose my HTML and CSS files. Which means I only have to re-program my JS file, and that too not too much. That's great. So today I wish to make the following:
  1. Adding and fixing the GSAP completely.
  2. Fixing the Frustum at various locations and floors.
  3. Combining both the things in the application and finally polishing the product.
Tomorrow is the last day before my classes are going to start, and I will have to do this at any cost by today fucking.

By the way, there was a fix that was required in the mesh, since there was a region where two meshes were a bit too close to each other, almost overlapping, which created some problems in rendering. And thus I fixed it by just adjusting the position of the inner mesh. Given below is the image of it after and before fixing it.

Fucking hell, it's 20:35 and my Blender file got corrupted. This is the third time I am fucked up in making this fucking thing. Fucking hell!

OK, so I have spent some more time and fixed the Blender file from what I had messed up. And now all the GSAP and edges are renamed. I have also had much progress that I would like to share here. They are listed below:

  1. The Application Flow
  2. Complete Nomenclature of Edges and Nodes

This in itself took a lot of time. Now the thing that is left is the GSAP selection and animation, which I will be doing now. As I think about programming how each GSAP and their individual edges will behave in each phase of the application, I realised that the variable that I am maintaining, which is "Application Flow", is of great importance. This has helped me a lot in organising the functionality of the different features at different phases of the application.

Application Flow :
So I have already shown the picture of the flow above. Now given below is the picture of the application flow that I have developed.

I have only completed making the application flow equal to [0], [1], [2], [2.1], [2.2], [2.3].

Complete Nomenclature of Edges ands GSAP :
Now coming to the nomenclature, I have added the outer library edges and gsap, and it's picture is given below. I have also updated the grid variable with the added gsap and their corresponding gsap and nodes depending in the code to better make it work.

This time, just to be saved from all the unexpected accidents, I have pushed the complete application code into a separate branch on GitHub. And I am also maintaining an additional Blender file. Since in these two days, both my Blender and source files were corrupted or overwritten. This feels devastating, but thankfully I am on track now.


7/3/26

God, lots of progress has been done. And I am going to share it in here. Firstly, now I will be keep uploading the updated blender files in the GitHub releases because I have realised that, in the computers that I work on, my blender files keep on getting corrupted. And just to save myself from getting betrayed by these computers, I have started maintaining the releases. Also, the code of this second version is uploaded in the second branch of my GitHub repo, just to be safe from the accident that has happened in the past. Now coming to the progress.

  1. Complete application flow of [2 to 2.3] and [2.3 to 2.4] and [2.4 to 2.3] and [2.4 to 2.5] and [2.5 to 2.4] (which includes seeing the A* algorithm working)
  2. Re-designing the camera orientation in camera animation.
  3. Using the camera orientation to complete the application flow [1 to 1.1] and [1.1 to 1] and [2.5 to 2.6]

I have also decided that I will be keeping the outline of the application turned on always. This is just too good to be kept as an option to be enabled. Now coming to the
Application Flow :
Given below is the mind map of the application flow that was already shown above in Rough Sketch.


As seen, a significant improvement has been done. I have also added the floor focus option, which will direct the focus of the floor necessary for getting the full control of the floor. So what I have realised is that the maximum and minimum distance of orbital controls, along with the target point, must change for every floor chosen. And this floor focus function that I have introduced does that. It makes it easier to select a particular GSAP at any particular location. Anyways, moving on. One thing to note above is that I have selected the starting point to be some arbitrary point, and also the ending point to be some arbitrary point, and finally I am getting the path from the starting to the ending point (for which I have used some graph search algorithm). And that's an achievement.

Camera Orientation :
So the problem that I was facing was how will I make the camera face the right GSAP (which is the next GSAP) at a time when I don't really know the next GSAP. Earlier, if I were to summarize my approach, it was all hard coded. And now, after the inclusion of the graph search, to a lot of extent I have come out of the hard coded logic, which is a good thing. Now in order to solve the problem of orientating the camera to the right next GSAP, I am using this way where I will be drawing a straight line between the origin of the selected GSAP and the next GSAP. And then at a distance d I will find the final coordinates of the camera. And then I will use GSAP to animate the camera from the initial coordinate, which is the present one, to this final one. And this is how I will be doing the animation. Given below is the formula for finding the coordinates of the final point which is at a distance d from point A and lies on the line passing through points A and B.

In this case, all I needed was the selected GSAP and the target GSAP where the camera must be pointed. Then I would find the coordinates of the selected GSAP and the next GSAP and then, using the above logic, get the final coordinates of the camera and then animate the camera.

Given below is the visual way in which I validated my understanding.