---
title: Epic 3D | Interactive 3D Models for YOOtheme Pro
description: Add interactive 3D models to YOOtheme Pro. Let visitors rotate, zoom and view products in AR with a fast, privacy-friendly 3D viewer.
url: https://www.yoozecase.com/epic-3d
---

# Epic 3d

**Latest Version**

**Release date**

**Made for**

Joomla, Wordpress

**Price**

€25.00 (incl. 6 months of updates)

[🛒 Get it for Joomla 👍](https://shop.yoozecase.com/checkout/buy/94767982-abeb-4f93-8604-66e4ac725f14)

[🛒 Get it for WordPress👍](https://shop.yoozecase.com/checkout/buy/41212378-7949-49d0-8b0e-8781b70fd881)

[Demo page](https://www.yoozecase.com/epic-3d-demo)

Your page just gained depth. Drop a real 3D model straight into the YOOtheme builder and hand visitors the controls. They spin it. They zoom into every detail. On a phone they place it in their own room at true size with AR. This is Joomla in three dimensions.

![Epic 3d](https://www.yoozecase.com/files/epic-3d.png)

---

## Description

Real 3D. Right inside the YOOtheme builder.
Yoo 3D turns a plain GLB file into a living object on your page. Upload it. Drop the element into the builder. Done. Visitors grab the model with their mouse and turn it through full space. They zoom into the stitching the grain the polish. On a phone one tap drops the model into their own living room at real size with AR.

Show one hero model under the spotlight. Or line up a whole collection and let people move through it.

The 3D Model Gallery runs a slideshow of models through a single viewer so the page stays fast even with ten of them loaded. The 3D Model Grid lays your catalogue out as clean cards and opens each one big in a pop-up the moment someone clicks. Cards with no poster get a thumbnail rendered straight from the model.

Light it your way with soft studio shadows or a colour you choose. Pick a look preset and skip the fiddling. Add a custom loading animation for the heavy files. Everything runs from your own server so no visitor data leaves for anyone else.

This is your product seen from every angle. Depth is now part of the page.

---

#### Top voted

';
 }
 html += '

';
 if (oc.title) {
 html += '

##### ' + escapeHtml(oc.title) + '

';
 }
 if (oc.text) {
 html += '

' + escapeHtml(oc.text).replace(/\n/g, '
') + '

';
 }
 html += '

';
 }

 // Auto winner(s) - top N from the already vote-sorted features
 if (mode === 'auto_winner' || mode === 'both') {
 var n = oc.winnerCount | 0;
 if (n ';
 for (var i = 0; i ' +
 (w.image_url ? '

![](https://www.yoozecase.com/' + escapeHtml(w.image_url) + ')

' : '') +
 '' + (i + 1) + '' +
 '' + escapeHtml(w.title) + '' +
 '' + getIcon(this.cfg.voteIcon) + ' ' + (w.votes | 0) + '' +
 '';
 }
 html += '';
 }
 }

 if (html === '') {
 this.elOutcome.hidden = true;
 return;
 }
 this.elOutcome.innerHTML = html;
 this.elOutcome.hidden = false;
 };

 /**
 * Roadmap view (v3.2.0): renders the items as status columns, in the
 * canonical status order from cfg.statuses. Each column is an  inside
 * the existing .yc-fb-list ';
 }
 return html;
 };

 Board.prototype.renderItem = function (f, index) {
 var disabled = this.cfg.isClosed ? 'disabled' : '';
 var voted = f.voted ? ' yc-voted' : '';
 var descHtml = f.description
 ? '

' + escapeHtml(f.description).replace(/\n/g, '
') + '

'
 : '';
 var thumbHtml = f.image_url
 ? '

![](https://www.yoozecase.com/' + escapeHtml(f.image_url) + ')

'
 : '';

 // Status workflow (v3.0.0): badge for any non-default status. The
 // roadmap view (v3.2.0) skips the badge - the column already
 // communicates the status, a badge would be redundant noise.
 var st = (f.status || 'open');
 var labels = this.cfg.statusLabels || {};
 var statusBadge = (!this.isRoadmap && st && st !== 'open' && labels[st])
 ? '' + escapeHtml(labels[st]) + ''
 : '';

 // Design themes (v3.1.0): arena / neon / pixel render extra per-item
 // furniture - rank number, avatar (image or initials), a "leader" pill
 // on rank 1, and a "votes" label. Classic/colour themes are untouched.
 var t = this.cfg.theme || 'light';
 var themed = (t === 'arena' || t === 'neon' || t === 'pixel');
 var rank = (typeof index === 'number') ? (index + 1) : 0;
 var rankHtml = '', leaderHtml = '', avatarHtml = '', votesLabel = '';
 if (themed) {
 rankHtml = '' + pad2(rank) + '';
 if (rank === 1) {
 leaderHtml = '' + escapeHtml(this.cfg.leaderLabel || 'Leader') + '';
 }
 if (f.image_url) {
 avatarHtml = '

![](https://www.yoozecase.com/' + escapeHtml(f.image_url) + ')

';
 } else {
 avatarHtml = '

' + escapeHtml(initialsOf(f.title)) + '

';
 }
 votesLabel = '' + escapeHtml(this.cfg.votesLabel || 'votes') + '';
 }

 // Moderation overlay: subtle corner buttons, only when canModerate.
 // Buttons appear on hover/focus (styled in CSS). Even in customizer
 // preview we render them when canModerate is true so the moderator
 // can see what visitors with moderation rights will see.
 var modHtml = '';
 if (this.cfg.canModerate) {
 var parts = [];
 var hideTitle = escapeHtml(this.t('hideTitle', 'Hide this feature'));
 var deleteTitle = escapeHtml(this.t('deleteTitle', 'Delete this feature'));
 if (this.cfg.allowSoftHide) {
 parts.push(
 ''
 );
 }
 if (this.cfg.allowHardDelete) {
 parts.push(
 ''
 );
 }
 if (parts.length || (this.cfg.statuses && this.cfg.statuses.length)) {
 var sParts = parts.slice();
 if (this.cfg.statuses && this.cfg.statuses.length) {
 var opts = '';
 for (var si = 0; si ' + escapeHtml(sl) + '';
 }
 var setStatus = escapeHtml(this.t('setStatus', 'Set status'));
 sParts.push(
 ''
 );
 }
 modHtml = '';
 }
 }

 var mediaHtml = themed ? avatarHtml : thumbHtml;
 return (
 '' +
 leaderHtml +
 rankHtml +
 '' +
 mediaHtml +
 '

' +
 '

##### ' + escapeHtml(f.title) + '

' +
 statusBadge +
 descHtml +
 '

' +
 modHtml +
 ''
 );
 };

 /**
 * Detects whether a JSON response looks like a CSRF/token rejection.
 * Two cases:
 * 1. com_ajax-level rejection (Joomla's auto-token-check on POST): top
 * level message contains the JINVALID_TOKEN_NOTICE text and HTTP
 * status is typically 403.
 * 2. Plugin-level rejection from requireToken(): payload.error === "Invalid token".
 */
 Board.prototype.isTokenError = function (status, raw, payload) {
 if (status === 403) return true;
 var hay = '';
 try { hay = JSON.stringify(raw || {}) + '|' + JSON.stringify(payload || {}); } catch (e) {}
 return /invalid (security )?token/i.test(hay);
 };

 /**
 * Fetch a fresh CSRF token from the server. Updates this.cfg.csrfToken so
 * the next call (and any future calls in this Board's lifetime) use the
 * correct one. Cache-bust with a timestamp so no upstream CDN caches the
 * response.
 */
 Board.prototype.fetchFreshToken = function () {
 var self = this;
 var url = this.cfg.ajaxUrl + '&task=token&_=' + Date.now();
 return fetch(url, {
 method: 'GET',
 credentials: 'same-origin',
 headers: { 'Accept': 'application/json', 'Cache-Control': 'no-cache' }
 })
 .then(function (r) { return r.json(); })
 .then(function (data) {
 var p = self.unwrapAjax(data);
 if (p && p.ok === true && typeof p.token === 'string' && p.token.length >= 16) {
 self.cfg.csrfToken = p.token;
 return p.token;
 }
 throw new Error('No fresh token in response');
 });
 };

 /**
 * Generic POST-with-token helper. Builds FormData from a plain object,
 * adds the current token, posts. On 403 / token-error response, fetches a
 * fresh token and retries exactly once.
 *
 * @param {string} task The task name (appended to URL and body)
 * @param {object} fields Key-value form fields (no token)
 * @return {Promise

## Changelog

---

v2.4.14
 Breaking 16/07/2026

Fixed

- **Environment = Custom Color showed "3D model could not be loaded" even

v2.4.13
 Breaking 08/07/2026

Fixed

- **Empty-state placeholder text overlapped itself.** The stage sets

v2.4.12
 Breaking 08/07/2026

Fixed

- **Generated thumbnails showed the model tiny and off-centre** (grid and

v2.4.11
 Breaking 08/07/2026

Added

- **Auto-thumbnails for the gallery's Thumbnails navigation strip.** When
- **"Auto-generate Missing Thumbnails" now defaults to ON** on both the

Fixed

- **Auto-thumbnails never appeared (grid) and were missing (gallery).**

v2.4.10
 Breaking 08/07/2026

Fixed

- **3D Model Gallery showed no model at all (regression from 2.4.8).** The
- **Grid auto-thumbnails captured a blank image.** The hidden snapshot

v2.4.9
 Breaking 08/07/2026

Added

- **3D Model Grid: automatic thumbnails for models without a poster.** New
- Lazy - a model is only generated when its card scrolls near the
- Serialised - one hidden worker at a time, so there is never more than
- Cached - each result is stored in sessionStorage for the visit, keyed

Fixed

- **Grid: modal preload used fetch mode no-cors**, the same opaque-response

v2.4.8
 Breaking 08/07/2026

Fixed

- **3D Model Gallery: slides visibly overlapped during a swap ("the
- **Gallery: a later slide could stop loading.** The next-model preload

v2.4.7
 Breaking 08/07/2026

Changed

- **Settings panels consolidated to 5 tabs each** (4 plus the built-in
- 3D Model: Model | Motion | Camera & Lighting | Style & Loader
- 3D Model Gallery: Content & Gallery | Motion | Camera & Lighting |
- 3D Model Grid: Content & Grid | Modal | Motion & Camera |

v2.4.6
 Breaking 08/07/2026

Changed

- **Removed the diagnostic `data-yc-build` / `data-yc-anim` /
- **Moved the stylesheet read out of the element templates.** The three

v2.4.5
 Breaking 08/07/2026

Changed

- **All element icons redrawn from Tabler Icons** (MIT, stroke-based
- **The three elements now share one product picker colour**, teal
- **NOTICE.txt**: added the required "Third-party assets" section

Fixed

- **Builder element icons rendered far too large.** The SVGs carried no
- **Icons are now referenced as inline base64 `data:` URLs** in
