So basically I am trying to make a model loader, that will take in wavefont obj files and render them in webgl. Eventually I would like to be able to rotate, translate and scale these objects.
I have the interface all setup and it works nicely. However I am having problems with rendering.
I have taken in an obj file, and checked the arrays all have the correct numbers of elements and I even checked using chromes webgl debug plugin, and it appears the arrays match up (even element values match up).
Number of Vertices: 10932
Number of Indices: 18960
Anyway When I run gl.drawElements(gl.TRIANGLES, numItems, gl.UNSIGNED_SHORT, 0);
I get no chrome error but in the webgl plugin debug i get 'INVALID_OPERATION' with no additional information.
I have found that by changing numItems (which is usually the number of indices / 18960) to a much lower number, it will render a teapot (slightly wrong). The lucky number for some reason is 11034, if I go above this, it wont render, if I go below it will render my slightly wrong teapot. I need this number to really be the full number of indices, as obviously i cannot hard-code the numbers.
So I am very confused as to why this is happening, for my full code for debug:
http://webdesignscript.net/assignment/graphics_a3/
Rendering part of the code:
http://webdesignscript.net/assignment/graphics_a3/scripts/webglengine.js
Teapot model that is loaded:
http://webdesignscript.net/assignment/graphics_a3/models/teapot.obj
Cheers, Josh
I hope you remembered that the faces in OBJ files use vertex indices that start at 1, rather than 0. So perhaps those later faces (that make it crash or not work) just reference an invalid vertex (one past the end). If so, just subtract 1 from the faces' vertex indices after read from the file.
Related
When working on a SolidJS project you might start seeing the following warning message in your JS console:
computations created outside a `createRoot` or `render` will never be disposed
There are some information available on this in SolidJS' Github repository issues. But after reading them I was still not quite sure what this was all about and whether my code was really doing something wrong.
I managed to track down where it came from and find a fix for it based on the documentation. So I'm providing the explanation and the solution for those Googling this warning message.
In essence this is a warning about a possibility of a memory leak due to a reactive computation being created without the proper context which would dispose of it when no longer needed.
A proper context is created a couple of different ways. Here are the ones I know about:
By using the render function.
By using the createRoot function. Under the hood render uses this.
By using the createContext function.
The first is by far the most common way, because each app has at least one render function call to get the whole show started.
So what makes the code go "out of context"?
Probably the most common way is via async calls. The context creation with its dependency tree happens only when the synchronous portion of the code finishes running. This includes all the export default function in your modules and the main app function.
But code that runs at a later time because of a setTimeout or by being in an async function will be outside of this context and any reactive computations created will not be tracked and might stick around without being garbage collected.
An example
Let's say you have a data input screen and have a Save button on it that makes an API call to your server to save the data. And you want to provide a feedback to the user whether the operation succeeded or not, with a nice HTML formatted message.
[msg,setMsg] = createSignal(<></>)
async function saveForm(){
...
setMsg(<p>Saving your data.<i>Please stand by...</i></p>)
const result=await callApi('updateUser',formData)
if(result.ok){
setMsg(<p>Your changes were <b>successfully</b> saved!</p> )
} else {
setMsg(<p>There was a problem saving your data! <br>Error: </p><pre>{result.error}</pre> )
}
}
...
<div>
...
<button onClick={saveForm} >Save</button>
{msg()}
</div>
This will produce the above mentioned warning when the API call returns an error, but not the other times. Why?
The reason for this is that SolidJS considers the code inserts inside JSX to be reactive, ie: need to be watched and re-evaluated. So inserting the error message from the API call creates a reactive computation.
The solution
I found the solution at the very end of the SolidJS doc. It's a special JSX modifier: /*#once*/
It can be used at the beginning of a curly brace expression and it tells the SolidJS compiler to explicitly not to make this a reactive expression. In other words: it will evaluated once and only once when the DOM nodes are created from the JSX.
In the above example here's how to use it:
setMsg(<p>There was a problem saving your data! <br>Error: </p><pre>{/*#once*/ result.error}</pre> )
After this there will be no more warning messages :)
In my case, I had an input and when that input changed I re-created an SVG drawing. Because the SVG creation was an expensive operation, I added a debounce in the createEffect function which ran when the input changed. debounce is a technique to defer the processing until the input stops changing for at least X amount of time. It involved running the SVG generation code inside the setTimeout function, thus being outside of the main context. Using the /*#once*/ modifier everywhere where I inserted an expression in the generated JSX has fixed the problem.
Below are the various transforms I have found so far using NOP_VIEWER.model.getData().
I'm using the transforms to bring a position into viewer space, and I haven't been able to find any good documentation describing what they all do. My hope here is that this question can help by providing some documentation of the role of these transforms and how/when to use them.
The model originally comes from Revit.
GlobalOffset (Vector3)
placementWithOffset (Matrix4) - seems to be just the inverse of GlobalOffset as a matrix?
placementTransform (Matrix4) - undefined in all models I've tested, I've seen some hints that this is a user defined matrix.
refPointTransform (Matrix4)
Also, there are some transforms in the NOP_VIEWER.model.getData().metadata. These may be Revit specific:
metadata.georeference.positionLL84 (Array[3]) - this is where the model's GPS coords are stored
metadata.georeference.refPointLMV (Array[3]) - no idea what this is, and it has huge and seemingly random values on many models. For example, on my current model it is [-17746143.211481072, -6429345.318822183, 27.360225423452952]
metadata.[custom values].angleToTrueNorth - I guess this is specifying whether the model is aligned to true or magnetic north?
metadata.[custom values].refPointTransform - (Array[12]) - data used to create the refPointTransform matrix above
Can someone help by documenting what these transforms do?
Related: Place a custom object into viewer space using GPS coords
As an alternative solution, the Viewer works with extensions. The Autodesk.Geolocation extension provides a few methods to handle the data structure you mentioned:
Load extension:
let geoExt;
NOP_VIEWER.loadExtension('Autodesk.Geolocation').then((e) => {geoExt = e});
Or get already loaded extension:
let geoExt = NOP_VIEWER.getLoadedExtensions()['Autodesk.Geolocation']
Then use the methods to convert the coordinates
geoExt.lmvToLonLat
geoExt.lonLatToLmv
Here is a quick article on it.
You may .activate() the extension to see additional information on the model geo location.
I've been playing around with this for a while now, and I think, I've - almost - cracked it, but I am still not fully satisfied with my solution.
So, what I want to do, is having a piece of content, a list of items, which would have two views: The standard HTML one, so people can view and edit it; and then a JSON endpoint for other services to consume.
First I thought it's a simple matter of creating two JSP scripts to render the content:
/apps/my-stuff/components/list-page/html.jsp
/apps/my-stuff/components/list-page/json.jsp
However the Apache Sling DefaultServlet seems to be rather ignorant of the json.jsp script.
As a second attempt, I created another script, in /apps/foundation/components/primary/cq/Page/json.jsp which will be actually called, and renders the page, as I expected. However there are a couple of worries/questions regarding this:
First of all, why is this being honoured by the system, and not the one in the more specific place?
The documentation states, that to find the appropriate renderer, first sling:resourceType will be inspected, then sling:resourceSuperType and then, only as a fallback will jcr:PrimaryType checked. However I think this is rather: jcr:PrimaryType, then the DefaultServlet, and then all the other things.
Most worryingly however, I have to admit, this is rather generic, so it'll break all the contnet with jcr:PrmaryType = Page, so that could have some side-effects.
A solution could be creating a new type: ListPage extends Page; and then create a renderer for that in /apps/foundation.... However I have this bad feeling, that might introduce other problems.
So my question is two fold: What is the proper way of doing this, and/or what am I missing from the way the URL -> script resolution is working in AEM/Sling. (Because it seems to be slightly different that described here and here.)
(Obviously I am trying to keep the default JSON renderer for other pages, as that might be needed for other things in the page. I am not even sure, changing this one page won't break the UI for this particular page...)
However the Apache Sling DefaultServlet seems to be rather ignorant of the json.jsp script.
Have you tried renaming your JSP like so: "list-page.json.jsp"?
If you're using AEM 6.3, you should look at Sling model Exporters. They allow you to automatically register a servlet against your Sling Model (that you can create to model your list content). That servlet can generate a JSON representation of the model for you using Jackson.
If you're not using AEM 6.3, I would suggest you create a servlet registered against your resource type and use an additional selector.
#SlingServlet(
selectors = "json",
resourceType = "my-stuff/components/list-page",
methods = "GET")
More information on Sling Servlets can be found here.
I load some textures in asynchronously at the beginning of my game, about 40-50 of them.
vector<string> textureFileNames;
textureFileNames.push_back("textures/particle.png");
textureFileNames.push_back("textures/menu_title.png");
...
textureFileNames.push_back("textures/timer_bar.png");
for (auto fileName: textureFileNames)
{
Director::getInstance()->getTextureCache()
->addImageAsync(fileName, CC_CALLBACK_1(LoadingLayer::textureLoadedCallback, this));
}
My textureLoadedCallback method does nothing funky; at this stage it simply increments a value and updates a progress timer. The callback is called from the main thread by cocos2d-x design, so I don't suspect any problems arise from there.
90% of the time this works fine. But sometimes it crashes in VS2012 midway through loading the textures:
Debug Assertion Failed!
Program: C:\Windows\system32\MSVCP110D.dll
File: C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\include\vector
Line: 1140
Expression: vector subscript out of range
Breaking at this point, I can see that it dies in the internals of vector, specifically the [] operator, and traces back through _Hash to the TextureCache::loadImage() method: auto it = _textures.find(asyncStruct->filename) on line 174 of CCTextureCache.cpp. _textures is defined as std::unordered_map<std::string, Texture2D*> _textures, a standard library unordered map. asyncStruct->filename resolves to the full path and filename of a texture to load.
Using the debugger, I can see that the filename is fine. I can see that _textures already contains the 19 textures before this one that it has processed just fine.
The fact that it seems to just be dying in the midst of the standard library doesn't strike me as right... but I'm unable to determine where CCTextureCache goes wrong. Only that it doesn't always fail, and that it's failing in an asynchronous thread. There's no concurrency bollocks going on with my code (as far as I know).
Is this a cocos2d-x bug, a VS2012 bug or a bug with my code I pasted above?
I think a potential cause could be that the for loop issues like 19 async image loads all at once, which may or may not be supported by that method. Try issuing the next async load only after your texture callback is called. That way no two async loads are performed simultaneously.
I'm using the WkHtmlToXSharp wrapper library in my project to generate PDF file from HTML.
I was using this library a lot of times in different PCs and, suddenly, I came across the following problem:
System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
at WkHtmlToXSharp.WkHtmlToPdfConverter.wkhtmltopdf_convert(IntPtr converter)
at WkHtmlToXSharp.WkHtmlToPdfConverter.Convert(String inputHtml)
at WkHtmlToXSharp.WkHtmlToPdfConverter.Convert()
at WkHtmlToXSharp.MultiplexingConverter.b_8()
--- End of inner exception stack trace ---
at Sanford.Threading.DelegateQueue.EndInvoke(IAsyncResult result)
at Sanford.Threading.DelegateQueue.Invoke(Delegate method, Object[] args)
at WkHtmlToXSharp.MultiplexingConverter.Convert()
This seems to be a common problem with this library (I've found some feedback on the web about it - however no fix was provided). BTW, in my case it happens somewhat randomly. I was not experiencing this problem in other dev machines. I wonder if somebody has a fix for it. I also wonder if this is a problem with the wrapper library, if with the WkHtmlToPDF library itself.
Any suggestion? I'm also open to use another converter, as long as it is free and stable and, if possible, without spawning a new process. It must work properly and stable in all Windows versions and do a decent job converting (the HTML to be converted is fixed - contains a few pics and tables and basic CSS).
I would suggest an alternate route: simply use wkhtmltopdf.exe directly, building your own wrapper. They are not very complicated if you have control of the input and then you know exactly how to update it and how the options work. I've never encountered with that problem when using wkhtmltopdf directly (on Win7, Win server 2008 r2, Ubuntu and CentOS). They do spawn process for every conversion though.
For an example, check out the Derp class in another answer of mine regarding wkhtmltopdf. Or try something like the untested code below (your true code will be more complicated, this is just a demo/POC).
var pi = new ProcessStartInfo(#"c:\wkhtmltopdf\wkhtmltopdf.exe");
pi.CreateNoWindow = true;
pi.UseShellExecute = false;
pi.WorkingDirectory = #"c:\wkhtmltopdf\";
pi.Arguments = "http://www.google.com gogl.pdf";
using (var process = Process.Start(pi))
{
process.WaitForExit(99999);
Debug.WriteLine(process.ExitCode);
}