Show and interact with 3D models

Hyouryuu-Na

Sapphire Sodium
Veteran
Joined
Jun 15, 2017
Messages
931
Reaction score
2,182
First Language
Not English
Primarily Uses
RMMV
Hello ^^ A few days ago I started experimenting with <model-viewer> and I was able to show 3D models in MV. This is a geat way to make item inspection more challenging and entertaining.
What does it looks like exactly?

In this tutorial I will show you how to do that using script calls. Though it's more like, I'll explain how to use it and you can decide how you want it to function.

What do you need?
1. A software like Blender 2.8 to convert models to glb or gltf.
2. Photoshop or Gimp to edit textures if needed.
3. At least 6 free variables and 2 common event slots.

This is a pretty text and picture heavy tutorial so I'm putting segments in spoilers.

Adding necessary scripts to project
First of all, you have to get these two js scrips:
model-viewer.min.js
model-viewer-legacy.js
There are two ways you can handle them in your project:
1. Place them inside your js/plugins/ folder and include them as plugins in the plugin manager:
*Note! Rename model-viewer.min to model-viewer-min or model-Viewer_min.
1599827899711.png
Or
2. Link these plugins directly to the index.html file:
1599827959963.png
It’s better to use a code editing software for this. Notepad++ should work fine.
There is not much difference between these two but I like to separate dependency scripts and put them directly in the html file as it helps to keep my plugin manager cleaner and only list plugins I can modify.

Getting models ready
Let’s get a glb model for testing. For this tutorial I just went to archive3D and got a globe. It came in a bunch of formats but what we need is a .glb or a .gltf model. So convert it if your model doesn’t come in that format. And always keep notes where you got the model from.
If you have Microsoft’s 3D viewer installed, the model viewer can be converted to a glb model without any hassle. But if you don’t, you can use Blender. Blender 2.8+ has built-in support for glTF files.

I just used 3D viewer.

*Note! The model must be fairly large.
How large I can’t really say since I sometimes use pmx editor for quick edits and it’s a very simple editor so I have no idea about the scale. But I usually scale it up like, 10x, 100x, 10x XD So, very large. Before you scale your models though, load it up and see if you can see a red block (if you follow my instructions and put in the exact same style I will give you later on). If you can’t, then your model needs scaling.

Put your glb model in a separate folder just to keep your project files organized.
I put this globe in a new folder in the root folder named 'models'.

Brief explanation of the tag and attributes
Before we actually start working, let’s take a look at the <model-viewer> html tag. I’ll explain what each attribute does. And for those who have no idea what I’m talking about:

HTML:
<div id="test" style="width: 100%; height: 100%;"></div>
Here,
<div></div> ---> Opening and closing tag
id, style ---> Attribute
width, height ---> Property

For the <model-viewer> tag, we’ll use this setting:
HTML:
<model-viewer id="" rotation-per-second="" loading="" interaction-prompt= "" ar="" auto-rotate auto-rotate-delay="" ar-modes="" camera-controls="" src="" data-js-focus-visible="" ar-status="">
</model-viewer>
id = The name/identity that’s given to an element. Having an id is very useful as you can use it to control different properties of the element from the outside via javascript.

style = The css style of the element. There are many properties that we can assign using the style attribute but we will mainly use width, height, left and top. I’ll come to this later.

rotation-per-second = How many times the model will rotate per second. The unit is degree or radian.

loading = The loading type of the model. “Eager” makes the model show as soon as it’s loaded. “Lazy” doesn’t show the model till it’s interacted it. Default is lazy but we will use eager.

interaction-prompt = Whether there should be a little hand pointing to the model to tell the user to interact with it or not. I set this to “none” but if you want it you can set it to “auto”

auto-rotate = turns on auto rotation. Doesn’t accept values.

auto-rotate-delay = How long should the model wait before starting to rotate. I use 0.

src = The source of the model. In my case its inside the models folder that I made so the source is “models/model_name.glb”

The other ones don’t really matter so I won’t explain them.

We will also use buttons to create clickable areas in the model. So that when the player inspects them, different common events can be triggered. Let’s look at the button tag and its attributes:
HTML:
<button onClick="" slot="" data-position="" data-normal="">
</button>
onClick = This is the common event/js function to be triggered when the button/hotspot is clicked.

slot = This is sort of like id. It will give the button an identity and the button will follow the model as it moves. This MUST start with hotspot- otherwise it won’t work. Example: hotspot-hand (a clickable area in the hand of the model)

data-position = The x,y and z coordinates that we will use to position the hotspot. You will need to play around with the values to find the perfect one for your model.

style = same as the style attribute used in the model-viewer tag. This will let us change the size and colour of the buttons/clickable areas.

data-normal = Not really sure what this does. But it’s necessary so don’t leave it blank. Just put in whatever 0 0 1, 1 0 0, 0 0 0 whatever you want.

You’ll see what type of values to insert in all the attributes from examples I will show you later.

Making common events for showing models
Make a new div in the body section of index.html:
HTML:
<div id="model"></div>
You can name the id however you want but make sure to change the #model in the style to #yourPrefereredName (see below)

Add this to the head section of index.html:
HTML:
<style>
#model{
    z-index: 7;
}
model-viewer {
          width: 100%;
          height: 100%;
          position: fixed;
          outline: none;
          position: fixed;
          --poster-color: transparent;
          z-index: 7;
        }
button{
    display: block;
    width: 20px;
    height: 20px;
    border-radius: 10px;
    border: none;
    background-color: blue;
    box-sizing: border-box;
}
:not(:defined) > * {
    display: none;
}
</style>
Make a common event. We’ll make id and src attributes. Why? To make this thing universal. So that you can show any model you like without making countless model-viewer tags.
Script call:
JavaScript:
var loadModel = function(var1){
var model= `<model-viewer id="`+var1+`" style="width: 100%; height: 100%; left:0%; top: 0%;" rotation-per-second="30deg" loading="eager" interaction-prompt= "auto" ar="" auto-rotate auto-rotate-delay=0 ar-modes="webxr" camera-controls="" src="models/`+var1+`.glb" data-js-focus-visible="" ar-status="not-presenting">
</model-viewer>`
return model;
}
document.getElementById("model").innerHTML += loadModel($gameVariables.value(1)); //Change model to whatever you set as the div's id.
//Feel free to change the variable ID to something else.
How it looks like:
1599830635448.png

Also, let's make another common event for showing hotspots. We need this because you might need to make multiple buttons for one model, let alone several other models. Are we manually going to make these buttons? No. We will generalize it with a common event.
JavaScript:
var loadHotspots = function(var2, var3, var4, var5){
var buttons =`<button onClick="$gameTemp.reserveCommonEvent(`+var4+`)" slot="`+var5+`" data-position="`+var2+`" data-normal="`+var3+`"></button>`
return buttons;
}
document.getElementById($gameVariables.value(1)).innerHTML += loadHotspots($gameVariables.value(2), $gameVariables.value(3), $gameVariables.value(4), $gameVariables.value(5));
//Feel free to change the variable IDs used.
What it looks like:
1599830833803.png

To delete a model, you don’t need to make a common event as it’s just one line of code whenever you want it to not be on the screen anymore.
JavaScript:
document.getElementById("<model you used in Variable 1 to show the model>").remove();
Now the model is permanently deleted, freeing up space.

Implementation
Let's make an event:
1599831206792.png
What did I do here? I set the model's name and source which is stored in Variable 1 to 'globe'. That's the name of my model which is in the models folder. If you feel that you need two different isntances of the same model, the you just need to assign a different variable, say, variable 6 as id. I just didn't see the need for it.
I also set the data position, data-normal, triggered common event ID and slot name. Slot name MUST begin with 'hotspot-'
The I called the show model common event. Then I called buttons common event.
*Note! You can set multiple hotspots. you just need to change the variable values 2-5 before calling buttons common event.
After 200 frames, the model is deleted.

Well then, let's see how it looks like in-game:
1599832253775.png
Too big! It's even covering our text box! (Which we triggered by clicking the red box).

Let's change that.
Back to our event! Add this just under the buttons common event:
JavaScript:
var model = document.getElementById($gameVariables.value(1));
model.style.width = "70%";
model.style.height = "70%";
1599832089324.png

Now it looks like this:
1599832195588.png
To much to the left! Let's position it. Back to the event!
Add this:
JavaScript:
model.style.left = "15%";
model.style.top = "10%";
1599832388270.png
Now what does it look like?
1599832492083.png
What if I add another button?
1599832528094.png

Phew! We are mostly done. But not yet. Want to make the red box transparent so that the player doesn't know where to click?
Change the css we put in the index.html file:
HTML:
button{
            display: block;
            width: 40px;
            height: 40px;
            background-color: transparent;
            background-repeat:no-repeat;
            border: none;
            cursor:url(icon/magnify.png), auto;
            overflow: hidden;
            outline:none;
        }
I made the background transparent and now if you hover over the block, you'll see a different icon. Delete it if you don't want that. You can also control the width and height of the button here.

Important! Please Read- Things to note
1. The models might look very blurry when loaded. If your game runs on <50 fps, the model's texture gets auto resized. I haven't found a way to stop that. So the best way to show crisp models would be to transfer the player to a very minimal map or take a screenshot of the current map and use it as a picture in a completely empty map. I'm not sure if it will happen to everyone but I use gridfree doodads, lighting plugins and shadow plugins, my screen resolution is huge (1920x1080) so it's possible that it won't happen to you.
2. The map doesn't pause when you load the model. So use a plugin to stop map movement till it is removed or the player will keep moving when you move the model and vice versa.
I have a simple fix for this though.
stop all input:

JavaScript:
if($gamePlayer.moveByInputCached === undefined)
    $gamePlayer.moveByInputCached = $gamePlayer.moveByInput;
$gamePlayer.moveByInput = function(){
    return false;
}
Enable all input:
JavaScript:
$gamePlayer.moveByInput = $gamePlayer.moveByInputCached;
3. If you don't see the hotspots, your model is too tiny. Scale it up by a few tens.

Edit 18/09/2020:
4. If you don't want to enable zooming in and out, edit the model-viewer_min and legacy js files to get rid of all event listeners that listen for the wheel. Or you can just replace them with these:
model-viewer_min.js
model-viewer-legacy.js

Anyways, hope this helped someone even if it looks very tedious. Enjoy ^^


Demo:
 
Last edited:

joepmeloen

Veteran
Veteran
Joined
Feb 23, 2019
Messages
39
Reaction score
12
First Language
Dutch
Primarily Uses
RMMV
This is awesome, it does add new functions to a game with a ton of good uses, like mistery / detective kind of game.

Is there any free database with 3d objects to be used?
 

Hyouryuu-Na

Sapphire Sodium
Veteran
Joined
Jun 15, 2017
Messages
931
Reaction score
2,182
First Language
Not English
Primarily Uses
RMMV
Archive3D has a lot of free to use models. But I'm not entirely sure about the terms of use of these models. They say the models can be 'freely modificated or elaborated' but says nothing about giving credits... To be safe, you should credit the uploader and just mention that models were taken from Archive3D.
 

KotoYama

Veteran
Veteran
Joined
Apr 20, 2019
Messages
148
Reaction score
12
First Language
Spanish
Primarily Uses
RMMV
It looks great, but I think it doesn't work for me cause I didn't quite get the "Brief explanation of the tag and attributes" part. What is this <model-viewer> html tag you're talking about? Do you mean I should put it inside the index file?

P.S. I would love to see a plugin for that! I think its popularity will only grow when people get used to MV3D and Ultra Mode 7! There is one $10 plugin on itch, but I'm hesitant to buy it cause I'm not 100% it'll work for me and if I even need it for my game.
 

Hyouryuu-Na

Sapphire Sodium
Veteran
Joined
Jun 15, 2017
Messages
931
Reaction score
2,182
First Language
Not English
Primarily Uses
RMMV
@KotoYama
The brief explanation of the tags and attributes part is just an explanation of the tags and attributes one can edit to suit their own needs. The real tutorial is the making common events for showing models.
I have a somewhat working plugin ready but know that I'm not a pro when it comes to coding. I don't also get the various classes, functions stuff of the rpg maker core files. Hence this plugin is built solely relying on html which I have quite a good grasp on. I'll see if I can post it soon though.
 

KotoYama

Veteran
Veteran
Joined
Apr 20, 2019
Messages
148
Reaction score
12
First Language
Spanish
Primarily Uses
RMMV
@Hyouryuu-Na
I see. Welp, I'll be certainly waiting for it.
Hmm... Could you check if I'm missing something here?
1603546813108.png
1603546926821.png1603546947589.png
I have my globe model(single file, gbl format) in gametitle\Models.
I've copied the common events exactly as you told.
The problem is that I don't see any model. I've tried scaling it but nothing.
 

Hyouryuu-Na

Sapphire Sodium
Veteran
Joined
Jun 15, 2017
Messages
931
Reaction score
2,182
First Language
Not English
Primarily Uses
RMMV
It looks fine to me. Does the model not show up? Hmm... I'll post a demo today. I do feel like a demo will be pretty useful for a lot of people as this thing is pretty complex to understand from screenshots alone.
 

KotoYama

Veteran
Veteran
Joined
Apr 20, 2019
Messages
148
Reaction score
12
First Language
Spanish
Primarily Uses
RMMV
@Hyouryuu-Na
Sounds great :) I don't know, maybe something wrong with my variables in the common events? I've decided to use variables from 61 - 66. "game.Variables.value()" is the only thing I've changed.
1603548348276.png
1603548366168.png
 

Hyouryuu-Na

Sapphire Sodium
Veteran
Joined
Jun 15, 2017
Messages
931
Reaction score
2,182
First Language
Not English
Primarily Uses
RMMV
Found the issue XD
Put this inside the style in head of the html file:
HTML:
model-viewer {
          width: 100%;
          height: 100%;
          position: fixed;
          outline: none;
          position: fixed;
          --poster-color: transparent;
          z-index: 7;
        }
 

KotoYama

Veteran
Veteran
Joined
Apr 20, 2019
Messages
148
Reaction score
12
First Language
Spanish
Primarily Uses
RMMV
Still nothing I'm afraid :D
I've tried different plugin placement but no luck. I'm also getting script call errors :(
1603551348975.png
1603551097946.png
 

Hyouryuu-Na

Sapphire Sodium
Veteran
Joined
Jun 15, 2017
Messages
931
Reaction score
2,182
First Language
Not English
Primarily Uses
RMMV
@KotoYama The syntax seems to be wrong. Did you copy the codes properly? Start in a fresh project I guess. It's hard to pinpoint what seems to be the issue. I'm almost done with a demo (I was done actually until I noticed some things that I have to sort out ^^; ) So it'll have to wait for a while.
 
Last edited:

KotoYama

Veteran
Veteran
Joined
Apr 20, 2019
Messages
148
Reaction score
12
First Language
Spanish
Primarily Uses
RMMV
@Hyouryuu-Na
Alright! It works! It was a syntax error. Also, you've said I'll be needing at least six variables but I only ended up using five. And scaling didn't seem to be an issue at all. Seems like the plugin auto-scales the model by itself. At least for me, it did.
 

Hyouryuu-Na

Sapphire Sodium
Veteran
Joined
Jun 15, 2017
Messages
931
Reaction score
2,182
First Language
Not English
Primarily Uses
RMMV
I ended up not using a variable. By scale I meant the actual size of the model, not the display scale. Sometimes if they're too small, the hotspots aren't visible. Glad it works for you ^^
 

KotoYama

Veteran
Veteran
Joined
Apr 20, 2019
Messages
148
Reaction score
12
First Language
Spanish
Primarily Uses
RMMV
Hmm... Yeah, as you've said, I end up getting very blurry models. Transferring to another map isn't an option for me (the player would get lags reloading the old map).
I wish I could get at least something pixelated, but not blurry since it clashes with my game's style.

I think, at least for me, the main problems are those white contours on my models I'm getting. They are really visible since I'm using a black background.
 
Last edited:

Hyouryuu-Na

Sapphire Sodium
Veteran
Joined
Jun 15, 2017
Messages
931
Reaction score
2,182
First Language
Not English
Primarily Uses
RMMV
I don't think there's anything to do about the blurry models since we'd have to alter the code that renders it in the main js file. And I don't think I'm capable of doing it. You can ask in the forum if anyone knows how to solve this.
As for the white counter, I don't understand what you mean by it. Can you describe more?
 

KotoYama

Veteran
Veteran
Joined
Apr 20, 2019
Messages
148
Reaction score
12
First Language
Spanish
Primarily Uses
RMMV
Of course, sorry for my English :DD I meant contours (the outline if you will)!
I don't know if you can see it on this picture. I think it's just the lightened parts of the model getting all blurry.

I dought it's fixable anyway, so... :(
1604162248117.png
 

Hyouryuu-Na

Sapphire Sodium
Veteran
Joined
Jun 15, 2017
Messages
931
Reaction score
2,182
First Language
Not English
Primarily Uses
RMMV
That's the shading. If you don't it to have highlights, edit it in a software like blender to turn down the reflection.
 

KotoYama

Veteran
Veteran
Joined
Apr 20, 2019
Messages
148
Reaction score
12
First Language
Spanish
Primarily Uses
RMMV
Oh, I see. Thanks. I'll check it out! :)

@Hyouryuu-Na Is there at least any way to change the model's scaling? I managed to reproduce the pixelated effect in blender, but have no idea whether it's possible to do the same in maker.
 
Last edited:

Hyouryuu-Na

Sapphire Sodium
Veteran
Joined
Jun 15, 2017
Messages
931
Reaction score
2,182
First Language
Not English
Primarily Uses
RMMV
Sorry for the late reply.
You mean make the models look not blurry in RM? The models aren't being scaled. It's the texture that's being scaled down. I'm pretty sure it's not possible unless you can maintain fps between 50-60. I've noticed that even a slight drop in fps causes the texture to scale down. I'll look into it but I doubt I know where to look lol the code is huge. In the meantime you can try pausing all map movement with plugins before loading the model. That should help.
 

Users Who Are Viewing This Thread (Users: 0, Guests: 1)

Latest Threads

Latest Profile Posts

Once again working on a game I'm not sure I'm going to sell or even publish
That feel when you're awake past midnight and suddenly you're one year older :ninja:
I miss collaborations, but I don't know how to find someone to make face parts just to share them with others, and even though I don't like writing or music, I can't trust anyone with writing on my game because it has themes that are easy to mess up, and music needs a clear tone and scenes.
People donating to me for my upcoming birthday so I can pay my team a little. Such angels, I'm so happy. T uT I smile so much my face hurts. Good souls in this world.
Playing Ragnarok Online again is very nostalgic. The last time I played it was 20 years ago, when I was ten-twelve old.
My first mmorpg.^^

Forum statistics

Threads
105,571
Messages
1,014,721
Members
137,245
Latest member
dashstop
Top