Create your Own Coronavirus in 3D

Zoom and rotate your own COVID-19 —in 20 lines of code.

Meinhard Ploner
Analytics Vidhya
4 min readMar 21, 2020

--

Screenshot of the App

This brief story is about how you can easily visualise a 3D model of the Coronavirus. The resulting miniature web app allows you to interact with the “virus” via the mouse.

Amidst the Coronavirus crisis we get a lot of case number updates, research and forecasts. Because of the lockdown I have a lot of time to my disposal. Last weekend I created two web apps to download and visualise COVID-19 case numbers (see Medium Posts: Python-Dash, R-Shiny). Now I spent some time on something even more playful: 3D visualisation.

The implementation of this app will be done using R. The R language is mostly used by Statisticians and Data Scientists, but it also has a very good package to handle 3D visualisations using OpenGL (package “rgl).

This story will show how to solve the task and is divided into two parts:

  1. Get it running: 101 on getting the app running.
  2. How it works: code understanding.

Get it running

Download the 3D Model

First let us download a free 3D model in a format we understand. I found on Sketchfab a model with 85k vertices (CC license, Evan Pachon). Download and save the file in the original format (obj).

Set up the Development Environment

If you have no R installation on your PC, then follow the “Step 1” described in my last post and open RStudio. Replace the package installation code by:

> packages = c("shiny", "rgl", "shinycssloaders", "readobj")
> install.packages(packages)

We will see later-on what the packages are for. Now create a new empty Shiny Project. Again — if you are new to R — simply follow the “Step 2” of the mentioned post. However, do not delete the file “app.R”, as we will use it as our main app file. Move the OBJ file obtained in the last section into this folder.

The “Little” Coding

All you need is the following small code block. Replace the existing content of “app.R” with these few lines.

library(shiny)
library(rgl)
library(shinycssloaders)
library(readobj)
ui = fluidPage(
titlePanel("Coronavirus / COVID-19 in 3D"),
fluidRow(
rglwidgetOutput("rglWidget", width="100%") %>% withSpinner()
)
)
server = function(input, output, session) {

output$rglWidget = renderRglwidget({
model = read.obj("coronavirus.obj", convert.rgl=TRUE)
open3d()
shade3d(model$Layer_1, color="darkgray")
shade3d(model$Layer_2, color="red")
bg3d(gray(level=0.95))
rglwidget(reuse=TRUE)
})
}
shinyApp(ui=ui, server=server)

That’s it. You can start the app by pushing the button called “Run App”:

By clicking the “Run App” button, there appear also some additional options. Check the option “Run External”, re-run the app, and it will launch in your default browser.

Btw, if you are on a Mac you might need to download and install XQuartz in order to work properly.

Photo by Markus Spiske on Unsplash

How it works

A Shiny app is divided into two parts: the user interface (ui) and the server.

Our UI is composed of a so called fluid layout, which is assembled by rows and columns. We need only a title row and an additional fluid row which contains the GL widget. The function rglwidgetOutput is part of the rgl package and creates the placeholder for the rendered model. It will be referenced in the server code by its outputId (“rglWidget”).

ui = fluidPage(
titlePanel("Coronavirus / COVID-19 in 3D"),
fluidRow(
rglwidgetOutput("rglWidget", width="100%") %>% withSpinner()
)
)

The method call “withSpinner()” (package shinycssloaders) after the pipe operator (“%>%”) replaces the widget by an animated spinner while the model is loading, which can take a couple of seconds.

The server code implements the logic to load and render the 3D model. “read.obj(…)” from package readobj reads the OBJ file and converts it to a format rgl understands. Then “open3d” opens a new graphics window. The function “shade3d” is used to add the two layers of the 3D model with the assigned colors (red and dark-gray). At last, “bg3d” sets the background color.

“rglWidget” is needed to produce a WebGL version of the scene, which can be rendered.

server = function(input, output, session) {

output$rglWidget = renderRglwidget({
model = read.obj("coronavirus.obj", convert.rgl=TRUE)
open3d()
shade3d(model$Layer_1, color="darkgray")
shade3d(model$Layer_2, color="red")
bg3d(gray(level=0.95))
rglwidget(reuse=TRUE)
})
}

Finally, this last code line creates the Shiny app itself.

shinyApp(ui=ui, server=server)
Photo by Jessica Knowlden on Unsplash

Final words

Obviously, this is a tiny showcase on how we can use R and rgl to visualise 3D models with very little effort.

But rgl offers much more:
lighting, materials, textures, animations, callbacks, etc.

Further, 3D models in formats such as OBJ or STL allow for easy feature extraction and model changes using R, Python or any other language. For a bigger project I was involved lately we additionally connected our R-Shiny app to the Python Freecad API to add additional out-of-the-box functionality.

As you see, there are no upward limits.

--

--

Meinhard Ploner
Analytics Vidhya

Manager Digital & AI @ GKN Hydrogen. Strong statistics and Machine Learning background. Loves excellent UI & UX. Creative and always open to new ideas.